如何在lua中不添加任何库将十进制转换为分数?

我正在制作一个纯lua运行的计算器,但我需要帮助将输出的小数转换为分数。

点赞
用户1944004
用户1944004

这是不可能的。你需要一个储存分数的类来实现。

你可以通过近似解决方案来达到目的。它适用于可以表达为分数的东西,但对其他所有的东西都会爆炸。

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)

输出:

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
2017-04-23 08:50:44
用户1847592
用户1847592

这个解决方案使用连分数来精确地还原分母高达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
2017-04-23 14:11:36