为什么2不等于√2*√2?

时间:2014-11-20 05:43:40

标签: math lua floating-point sqrt

根据Lua,我注意到2 ~= math.sqrt(2) ^ 2

print(2 == math.sqrt(2) ^ 2) --> false
print(2, math.sqrt(2) ^ 2) --> 2  2

为什么会这样?

3 个答案:

答案 0 :(得分:8)

大多数浮点数无法精确存储在Lua的数字类型中(默认为C double)。 math.sqrt(2)就是其中之一。

如果您尝试:

print(2 - math.sqrt(2) ^ 2)

输出:-4.4408920985006e-016这是一个非常小的数字,但仍然使这两个数字不完全相同。


这个浮点精度问题不仅存在于Lua中,还存在于许多其他语言中。正如@Thilo评论的那样,在比较实践中的平等时,你可以使用一个小的“delta”。您可能对以下内容感兴趣:C FAQ: What's a good way to check for ``close enough'' floating-point equality?

答案 1 :(得分:2)

以下推理表明,一般情况下sqrt(x)*sqrt(x) == x不能保留浮点运算中的所有操作数,无论是二进制还是十进制,即使平方根运算返回正确的舍入结果(如在符合IEEE-754浮点标准的现代计算机上通常就是这种情况。

在有限精度二进制浮点表示中,每个binade(两个连续2次幂之间的空间)包含相同数量的可精确表示的数字。对于IEEE-754单精度,每个binade有2个 23 这些机器号,对于IEEE-754双精度,每个binade有2个 52 这样的数量。

平方根是一种收缩操作,因为它将两个binades的输入域(例如[1,4])映射到只有一个binade的结果范围,比如[1,2]。因此,在IEEE-754双精度操作数的情况下,两个binades上的2个 53 可能的函数参数被映射到最多2个 52 个不同的平方根结果。如果我们现在对平方根运算的结果进行平方,我们最多可以得到2个 52 不同的产品,这些产品分布在两个能够代表2 53 机器数量的binades上。

因此,等式sqrt(x)*sqrt(x) == x最多可以保留一半可能的浮点输入。从实验上可以看出,它只适用于两个鳍的输入的一半。

另一方面,如果在产品计算中没有中间溢出或下溢,则等式x == sqrt (x * x)在IEEE-754浮点运算中保持不变。

答案 2 :(得分:-1)

浮点运算的本质在一般编程环境中非常重要。如果在浮点数上使用关系运算符,Classic C静态源代码分析程序(例如“lint”)实际上会给出警告。正如其他人所说,美国在比较中容忍。

但是,您选择的示例√2是无理性。没有计算数字系统可以保存该数字。它只能作为符号表达式。有一些符号编程系统可用:Octave-Symbolic,MathCAD,MATLAB,......现在是Wolfram(我认为)。他们将√2作为表达式,并将√2*√2评为2。