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

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

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

为什么会这样?

点赞
用户1009479
用户1009479

大多数浮点数在 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?

2014-11-20 05:49:15
用户780717
用户780717

下面的推理表明,在浮点算术中,无论是二进制还是十进制,即使平方根操作返回正确舍入的结果(这通常是符合 IEEE-754 浮点标准的现代计算机的情况),对于所有操作数都不可能使 sqrt(x)*sqrt(x) == x 成立。

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

平方根是一种收缩运算,因为它将输入定义域的两个区间(例如[1,4))映射到仅一个区间的结果范围中(例如[1,2))。因此,在 IEEE-754 双精度操作数的情况下,两个区间内的 253 个可能的函数参数被映射到至多 252 个不同的平方根结果。现在,如果我们对平方根操作的结果进行平方,我们最多会得到分散在可表示 253 个机器数的两个区间中的 252 个不同的乘积。

因此,等式 sqrt(x)*sqrt(x) == x 只能在可能的浮点输入的一半情况下成立。实验结果表明,它恰好在两个区间的一半输入中成立。

另一方面,等式 x == sqrt (x * x) 在 IEEE-754 浮点算术中确实成立,前提是在计算乘积时没有中间溢出或下溢。

2014-11-21 05:33:01
用户2226988
用户2226988

浮点运算的特性在一般的编程环境中非常重要。经典的 C 静态源代码分析程序(例如“lint”)实际上会在您对浮点数使用关系运算符时发出警告。正如其他人所说,请在比较中使用公差。

然而,您选择的示例√2是无理数。没有计算数系统能够表示这个数字。它只能以符号表达式的形式完全精确。现在有一些符号编程系统可用: Octave-Symbolic、MathCAD、MATLAB等....以及现在的 Wolfram(我认为)。它们会将√2保留为表达式,并将√2 * √2评估为精确的2。

2014-11-22 18:12:01