This task has been flagged for clarification. Code on this page in its current state may be flagged incorrect once this task has been clarified. See this page's Talk page for discussion.


The task is to write a program to transform a decimal number into a fraction in lowest terms.

It is not always possible to do this exactly. For instance, while rational numbers can be converted to decimal representation, some of them need an infinite number of digits to be represented exactly in decimal form. Namely, repeating decimals such as 1/3 = 0.333...

Because of this, the following fractions cannot be obtained (reliably) unless the language has some way of representing repeating decimals:

 67 / 74 = 0.9(054) = 0.9054054...
 14 / 27 = 0.(518) = 0.518518...

Acceptable output:

 0.9054054 → 4527027 / 5000000
 0.518518 → 259259 / 500000

Finite decimals are of course no problem:

 0.75 → 3 / 4 


 
'   Uses convention that one repeating sequence implies infinitely repeating sequence..
'   Non-recurring fractions are limited to nd number of digits in nuerator & denominator
 
nd =3   '   suggest 3. 4 is slow. >4 is .......
do
    read x$
    data "0.5", "0.1", "0.333", "1 /3", "0.33", "0.14159265", "2^-0.5", "0.1 +0.9*rnd(1)"
    data "0.142857142857", "int( 1000*rnd(1))/int( 1000*rnd(1))","end"   '   always between 0 and 0.999999...
    if x$ ="end" then exit do
    print x$; " is ";
    type$ =check$( x$)
    print type$;
 
    if type$ ="recurring" then
        x   =val( mid$( x$, 3, ( len( x$) -2) /2))
        rep =( len( x$) -2) /2
        num =x
        den =10^rep -1
        gcd =gcd( num, den)
        print
        print " Calculating exact fraction for ", recurring$( x); " recurring & found";
        print num /gcd; " /"; den /gcd
        print
    else    '   non-recurring. Check numerators & denominators <1000
        x =eval( x$)
        print
        print " Looking for fractions that are close to "; using( "#.############", x); " & found ";
        eps =10^nd
        for n = 1 to nd
            for i =1 to 10^n -1
                for j =i to 10^n -1
                    fr =i /j
                    if abs( x -fr) <eps then
                        eps =abs( x -fr)
                        'print i; " /"; j; " = ", using( "##.############", fr), "with error +/-"; using( "###.#########", eps /x *100); " %"
                        ii =i: jj =j
                        if eps =0 then exit for
                    end if
                next j
                scan
                if eps =0 then exit for
            next i
            if eps =0 then exit for
        next n
        print ii; " /"; jj
        print
    end if
loop until 0
 
print
print "END."
 
end
 
function recurring$( x)
    recurring$ ="0."
    do
        recurring$ =recurring$ +str$( x)
    loop until len( recurring$) >=14
end function
 
function gcd( a, b)  '   thanks Uncle Ben..
    while b <>0
       t =b
       b =a mod b
       a =t
    wend
    gcd =a
end function
 
function check$( i$)
    check$ ="non-recurring"
    length =len( i$) -2     '   allow for the '0.'.
    if length /2 =int( length /2) then if mid$( i$, 3, length /2) =mid$( i$, 3 +length /2, length /2) then check$ ="recurring"
end function
 