Luaではmathを用いる.floorにバグが発生する問題


リード:
local testNum1 = 38.48
print("testNum1 = ", testNum1)

local testNum2 = testNum1 * 100
print("testNum2 = ", testNum2)

local testNum3 = math.floor(testNum2)
print("testNum3 = ", testNum3)

--[[
testNum1 = 	38.48
testNum2 = 	3848
testNum3 = 	3847  --     
]]

test:
local testNum, addNum = 0.01, 0.01
for i = 1, 10000 do
    if testNum * 100 ~= math.floor(testNum * 100) then
        print(i, testNum * 100, math.floor(testNum * 100))
    end
    testNum = testNum + addNum
end

--[[
...
2343	2343.0000000001	2343
2344	2344.0000000001	2344
2345	2345.0000000001	2345
2346	2346.0000000001	2346
...
5563	5562.9999999997	5562
5564	5563.9999999997	5563
5565	5564.9999999997	5564
5566	5565.9999999997	5565
5567	5566.9999999997	5566
...
]]

遡及:
LuaのNumberタイプは実際にdouble(二重精度浮動小数点型)であるため、小数点の場合、2つの小数点が等しく、等号は使用できないが、それらの差の絶対値は小さな数(例えばmath.abs(a-b)<10 e-6)より小さいことに特に注意しなければならない.プログラムの中でどのように2つの浮動小数点数が等しいと判断します
コンピュータはバイナリでデータを格納しているので、0.1のような数字はコンピュータに格納されているのは実は長い数字で、バイナリでは0.1は無限の無循環小数である可能性があります.だから、ある程度切り取って、切り取った後、実際の値と私たちが格納している値に小さな違いがあるのは避けられません.
これは5562.999999997と5563が私たちから見れば等しい2つの数をもたらし、mathを行っている.floorの後に偏差が現れた.math.floor(5562.99999999997)は5562に等しいように下に整列します!
同じ理屈だCeilも同じ問題があります!
だからLuaではmathを使う.floorとmath.Ceilの時はこの問題に注意しなければなりません!
 
Just Mark!