3

今日の朝、Lua スクリプトにバグが見つかりました。これは非常に奇妙に思えます。この評価はどうしてこのように失敗するのでしょうか? 例はここでテストできます

最初の例:

if( math.abs(29.7 - 30) <=  0.3 ) then
  result = 1
else
  result = 0
end
print("result = "..result )
-->> result = 0

2 番目の例:

if( 0.3 <=  0.3 ) then
   result = 1
else
   result = 0
end
  print("result = "..result )
-->> result = 1

3 番目の例

if( math.abs(29.7-30) == 0.3 )then
   print("Lua says: "..math.abs(29.7-30).." == 0.3")
else
   print("Lua says: "..math.abs(29.7-30).." ~= 0.3")
end
-->> Lua says: 0.3 ~= 0.3 WHAT?

私は本当に混乱しています。今後同様のバグを避けるために、これを理解したいと思います。ありがとう

4

2 に答える 2

8

Lua が (IEEE 754) 64 ビットの倍精度浮動小数点数を使用しているという事実に見舞われています。

次の例を見てください
> print(0.3 == 0.3)
true
> print(0.3 <= 0.3)
true
> print(0.3 >= 0.3)
true

0.3in memoryの実際の値は次のとおりです。
> print(string.format("%1.64f",math.abs(-0.3)))
0.2999999999999999888977697537484345957636833190917968750000000000

今あなたの例を見てください:
> print(math.abs(29.7-30) == 0.3)
false
> print(math.abs(29.7-30) >= 0.3)
true
> print(math.abs(29.7-30) <= 0.3)
false

の実際の値29.7-30は次のとおりです。
> print(string.format("%1.64f",29.7-30))
-0.3000000000000007105427357601001858711242675781250000000000000000

の実際の値math.abs(29.7-30)は次のとおりです。
> print(string.format("%1.64f", math.abs(29.7-30))
0.3000000000000007105427357601001858711242675781250000000000000000

楽しみのために、の値math.abs(-0.3)は次のとおりです。
> print(string.format("%1.64f", math.abs(-0.3)))
0.2999999999999999888977697537484345957636833190917968750000000000

あなたの問題には2つの解決策があります.1つ目はWhat Every Computer Scientist Should Know About Floating-Point Arithmeticを読み、それを理解してください:-)。2 番目の解決策は、数値に別の型を使用するように Lua を構成することです。ヒントについては、値と型を参照してください。

編集 問題を「解決」する別の方法を考えましたが、それはちょっとしたハックであり、常に機能するとは限りません。最初に float を固定精度の文字列に変換することで、lua で固定小数点数を使用できます。

あなたの場合、それは次のようになります:

a = string.format("%1.1f", math.abs(29.7 - 30))
print(a == "0.3")

またはもう少し堅牢です:

a = string.format("%1.1f", math.abs(29.7 - 30))
print(a == string.format("%1.1f", 0.3))

ただし、すべての比較で適切かつ同じ精度を使用するようにする必要があります。

于 2013-05-02T08:11:05.357 に答える
0

ご存知のように、浮動小数点には精度の問題があります

参照: http://lua-users.org/wiki/FloatingPoint

a = 1
if a < 1 then print("<1") end

印刷されません"<1"。実際に変わらない限りa

于 2013-05-02T07:37:06.257 に答える