Lua未能评估math.abs(29.7 - 30)<= 0.3

MRo*_*ues 3 lua

今天早上我发现我的Lua脚本上有一个bug,看起来非常奇怪.这种评估如何以这种方式失败?可以在此处测试示例

第一个例子:

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

第二个例子:

if( 0.3 <=  0.3 ) then
   result = 1
else
   result = 0
end
  print("result = "..result )
-->> result = 1
Run Code Online (Sandbox Code Playgroud)

第三个例子

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?
Run Code Online (Sandbox Code Playgroud)

我真的很困惑,我想了解这一点,以避免将来出现类似的错误.谢谢

jbr*_*jbr 8

你被Lua使用(IEEE 754)64位双精度浮点数这一事实所困扰.

请看以下示例
> print(0.3 == 0.3)
true
> print(0.3 <= 0.3)
true
> print(0.3 >= 0.3)
true

0.3内存中的实际值是:
> 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

你有两个解决方案,第一个是阅读每个计算机科学家应该知道的关于浮点算术的内容,并理解它:-).第二种解决方案是将Lua配置为使用其他类型的数字,请参阅提示的值和类型.

编辑 我只是想到了另一种"解决"问题的方法,但它有点像黑客,而且不保证永远不会工作.通过首先将float转换为具有固定精度的字符串,可以在lua中使用定点数.

在你的情况下,看起来像:

a = string.format("%1.1f", math.abs(29.7 - 30))
print(a == "0.3")
Run Code Online (Sandbox Code Playgroud)

或者更健壮一点:

a = string.format("%1.1f", math.abs(29.7 - 30))
print(a == string.format("%1.1f", 0.3))
Run Code Online (Sandbox Code Playgroud)

但是,您必须确保使用的精度对于所有比较都足够且相同.

  • 请注意,这是一个问题是测试完全相等的情况.虽然有些情况下您可以预期浮点计算的确切结果,但这不是其中一种情况.使用任意精度表示的替代方案在计算上非常昂贵,因此需要折衷.引用的文章深入解释. (2认同)