Fraction Library

Source-code only - please, don't post questions here.
Zamaster
Posts: 1020
Joined: Jun 20, 2005 21:40
Contact:

Fraction Library

Postby Zamaster » Feb 18, 2007 19:38

Well... heres one if you ever needed it for some reason. Those who dont know, fractions are very slow compared to regular precision calculations, they should only be used if infinite precision is required. Enjoy!


Fractions.bi

Code: Select all

Type Fraction
    as string  manifest
    as integer num, den
End Type
function FRAC_SetFraction(pstr as string) as fraction
    Dim as Fraction f
    Dim as integer t1,t2,t3, m
    t1 = INSTR(pstr, "(")
    t2 = INSTR(pstr, "/")
    t3 = INSTR(pstr, ")")
    If t1 = 0 or t2 = 0 or t3 = 0 Then
        Exit Function
        Beep
    Endif
    f.den = VAL(MID$(pstr,t2+1, t3-t2-1))
    If t1 <> 1 Then
        m = VAL(MID$(pstr, 1, t1-1))
        f.num = m*f.den+VAL(MID$(pstr, t1+1, t2-t1-1))
    Else
        f.num = VAL(MID$(pstr, 2, t2-2))
    Endif
    f.manifest = "(" & STR$(f.num) & "/" & STR$(f.den) & ")"
    Return f
End Function
function FRAC_ManifestAsMixedNum(p as fraction) as fraction
    Dim as integer divP, modP
    If p.den>p.num Then Exit Function
    divP = p.num\p.den
    modP = p.num MOD p.den
    p.manifest = STR$(divP) & "(" & STR$(modP) & "/" & STR(p.den) & ")"
    Return p
end function
function FRAC_ManifestAsStandard(p as fraction) as fraction
    p.manifest = "(" & STR$(p.num) & "/" & STR$(p.den) & ")"
    Return p
end function
function FRAC_Simplify(p as fraction) as fraction
    Dim as integer dcount, lv
    If p.num < p.den Then
        lv = p.num
    Else
        lv = p.den
    Endif
    Dim as integer nmod, dmod
    For dcount = lv to 2 step -1
        nmod = p.num MOD dcount
        dmod = p.den MOD dcount
        If nmod = 0 and dmod = 0 Then
            p.num /= dcount
            p.den /= dcount
        Endif
    Next dcount
    p = FRAC_ManifestAsStandard(p)
    Return p
end function
sub FRAC_EqualizeDen(byref p1 as fraction, byref p2 as fraction)
    dim as integer nd
    If p1.den <> p2.den Then
        p1.num = p1.num * p2.den
        p2.num = p2.num * p1.den
        nd = p1.den * p2.den
        p1.den = nd
        p2.den = nd
    Endif
end sub
function FRAC_Add(p1 as fraction, p2 as fraction) as fraction
    Dim as fraction f
    FRAC_EqualizeDen(p1,p2)
    f.num = p1.num + p2.num
    f.den = p1.den
    f = FRAC_ManifestAsStandard(f)
    Return f
end function
function FRAC_Subtract(p1 as fraction, p2 as fraction) as fraction
    Dim as fraction f
    FRAC_EqualizeDen(p1,p2)
    f.num = p1.num - p2.num
    f.den = p1.den
    f = FRAC_ManifestAsStandard(f)
    Return f
end function
function FRAC_Multiply(p1 as fraction, p2 as fraction) as fraction
    Dim as fraction f
    f.num = p1.num*p2.num
    f.den = p1.den*p2.den
    f = FRAC_ManifestAsStandard(f)
    Return f
ENd function
function FRAC_Divide(p1 as fraction, p2 as fraction) as fraction
    Dim as fraction f
    f.num = p1.num*p2.den
    f.den = p1.den*p2.num
    f = FRAC_ManifestAsStandard(f)
    Return f
End function
function FRAC_RealToFrac(rl as double) as fraction
    Dim as fraction F
    Dim as string  rls
    Dim as integer man,plcs,v,mantissa
    rls = str$(rl)
    man = INSTR(rls,".")
    If man = 0 Then
        F.num = rl
        F.den = 1
    Else
        plcs = LEN(rls) - man
        mantissa = VAL(RIGHT$(rls,plcs))
        plcs = 10^plcs
        v = VAL(LEFT$(rls,man-1))
        F.num = mantissa+v*plcs
        F.den = plcs
    Endif
    f = FRAC_ManifestAsStandard(f)
    Return f
end function
function FRAC_FracToReal(p as fraction) as double
    Dim q as double
    q = p.num/p.den
    Return q
end function


...
...

FracTest.bas

Code: Select all

Option Explicit

#Include "Fractions.bi"


Dim as Fraction a, b, c
a = FRAC_SetFraction("(2/3)")
b = FRAC_SetFraction("(1/4)")
c = FRAC_Add(a,b)
Print c.manifest
a = FRAC_RealToFrac(0.125)
a = FRAC_Simplify(a)
Print a.manifest
Print FRAC_FracToReal(a)


a = FRAC_RealToFrac(5)
b = FRAC_SetFraction("(1/2)")
c = FRAC_Divide(a,b)
Print FRAC_FracToReal(c)

sleep
end
acetoline
Posts: 228
Joined: Oct 27, 2006 6:50
Contact:

Postby acetoline » Feb 19, 2007 6:50

Nice work, Zamaster. Thanks for sharing.

And yeah, fractions do tend to be painfully slow; A lot of people want to use them blindly, when they can get by perfectly with just Double precision. Fractions are also useless when it comes to things like trigonometry and square roots (and no, you can't write a sin() function that takes in a fraction and outputs a fraction; for that you'd need an infinite set of digits. The same thing happens for a general square root - consider sqrt(2) ).

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 2 guests