0

i am working on a calculator running in pure lua but i need help with making the out put decimals in to fractions

joshua chris
  • 55
  • 12

2 Answers2

2

This solution uses continued fraction to exactly restore fractions with denominator up to 107

local function to_frac(num)
   local W = math.floor(num)
   local F = num - W
   local pn, n, N = 0, 1
   local pd, d, D = 1, 0
   local x, err, q, Q
   repeat
      x = x and 1 / (x - q) or F
      q, Q = math.floor(x), math.floor(x + 0.5)
      pn, n, N = n, q*n + pn, Q*n + pn
      pd, d, D = d, q*d + pd, Q*d + pd
      err = F - N/D
   until math.abs(err) < 1e-15
   return N + D*W, D, err
end

local function print_frac(numer,denom)
   print(string.format("%.14g/%d = %d/%d + %g", numer, denom, to_frac(numer/denom)))
end

print_frac(1,  4)            -->  1/4 = 1/4 + 0
print_frac(12, 8)            -->  12/8 = 3/2 + 0
print_frac(4,  2)            -->  4/2 = 2/1 + 0
print_frac(16, 11)           -->  16/11 = 16/11 + 5.55112e-17
print_frac(1,  13)           -->  1/13 = 1/13 + 0
print_frac(math.sqrt(3), 1)  -->  1.7320508075689/1 = 50843527/29354524 + -4.44089e-16
print_frac(math.pi,      1)  -->  3.1415926535898/1 = 80143857/25510582 + 4.44089e-16
print_frac(0,   3)           -->  0/3 = 0/1 + 0
print_frac(-10, 3)           -->  -10/3 = -10/3 + -1.11022e-16
Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64
1

This is not possible. You need a class which stores fractions for that.

You can achieve an approximate solution. It works nicely for things that can be expressed as fraction and blows up for everything else

local function gcd(a, b)
    while a ~= 0 do
        a, b = b%a, a;
    end
    return b;
end

local function round(a)
   return math.floor(a+.5)
end

function to_frac(num)
   local integer = math.floor(num)
   local decimal = num - integer

   if decimal == 0 then
      return num, 1.0, 0.0
   end

   local prec = 1000000000
   local gcd_ = gcd(round(decimal*prec), prec)

   local numer = math.floor((integer*prec + round(decimal*prec))/gcd_)
   local denom = math.floor(prec/gcd_)
   local err   = numer/denom - num
   return numer, denom, err
end

function print_frac(numer,denom)
   print(string.format("%d/%d = %d/%d + %g", numer, denom, to_frac(numer/denom)))
end

print_frac(1,4)
print_frac(12,8)
print_frac(4,2)

print_frac(16,11)
print_frac(1,13)

Output:

1/4 = 1/4 + 0
12/8 = 3/2 + 0
4/2 = 2/1 + 0
16/11 = 290909091/200000000 + 4.54546e-10
1/13 = 76923077/1000000000 + 7.69231e-11
Community
  • 1
  • 1
Henri Menke
  • 10,705
  • 1
  • 24
  • 42