## Fraction Library

Zamaster
Posts: 1020
Joined: Jun 20, 2005 21:40
Contact:

### Fraction Library

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, denEnd Typefunction 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 fEnd Functionfunction 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 pend functionfunction FRAC_ManifestAsStandard(p as fraction) as fraction    p.manifest = "(" & STR\$(p.num) & "/" & STR\$(p.den) & ")"    Return pend functionfunction 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 pend functionsub 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    Endifend subfunction 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 fend functionfunction 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 fend functionfunction 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 fENd functionfunction 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 fEnd functionfunction 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 fend functionfunction FRAC_FracToReal(p as fraction) as double    Dim q as double    q = p.num/p.den    Return qend function`

...
...

FracTest.bas

Code: Select all

`Option Explicit#Include "Fractions.bi"Dim as Fraction a, b, ca = FRAC_SetFraction("(2/3)")b = FRAC_SetFraction("(1/4)")c = FRAC_Add(a,b)Print c.manifesta = FRAC_RealToFrac(0.125)a = FRAC_Simplify(a)Print a.manifestPrint FRAC_FracToReal(a)a = FRAC_RealToFrac(5)b = FRAC_SetFraction("(1/2)")c = FRAC_Divide(a,b)Print FRAC_FracToReal(c)sleepend`
acetoline
Posts: 228
Joined: Oct 27, 2006 6:50
Contact:
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) ).