如何在没有添加库的情况下将lua中的小数写入一小部分?

时间:2017-04-22 22:52:12

标签: lua

我正在研究一个以纯lua运行的计算器,但我需要帮助将小数点输出到分数

2 个答案:

答案 0 :(得分:2)

此解决方案使用连续分数精确恢复分母,分母高达10 7

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

答案 1 :(得分:1)

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

您可以获得approximate solution。它可以很好地用于可以表示为分数的东西,并且可以用于其他所有东西

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