比较 JavaScript 中的两个数字,它们是双精度的事实以及 == 或 === 的使用呢?

Ale*_*lke 5 javascript floating-point comparison

当我用 JavaScript 编写代码时,我很少考虑在比较数字时使用 == 或 === 运算符的后果。然而,JavaScript 数字是双精度的,因此 == 和 === 不应该按原样使用。

从使用 === 比较两个数字的文档中,我们得到:

11.9.6 严格相等比较算法

比较 x === y,其中 x 和 y 是值,产生真或假。这样的比较如下:

  1. 如果 Type(x) 与 Type(y) 不同,则返回 false。

  2. 如果 Type(x) 未定义,则返回 true。

  3. 如果 Type(x) 为 Null,则返回 true。

  4. 如果 Type(x) 是 Number,那么

    一种。如果 x 是 NaN,则返回 false。

    湾 如果 y 是 NaN,则返回 false。

    C。如果 x 与 y 的 Number 值相同,则返回 true。

    d. 如果 x 为 +0 且 y 为 -0,则返回 true。

    e. 如果 x 为 -0 且 y 为 +0,则返回 true。

    F。返回假。

  5. 如果 Type(x) 是 String,那么如果 x 和 y 是完全相同的字符序列(相同的长度和相应位置的相同字符),则返回 true;否则,返回false。

  6. 如果 Type(x) 是布尔值,如果 x 和 y 都为真或都为假,则返回真;否则,返回false。
  7. 如果 x 和 y 引用同一个对象,则返回 true。否则,返回false。

注意此算法在处理有符号零和 NaN 方面与 SameValue 算法 (9.12) 不同。

非严格 == 运算符在比较两个数字(4.a 到 4.f)时具有相同的算法,只是它允许将字符串转换为数字。

那么......语言本质上是在以一定的精度测试浮点数还是使用在 C/C++ 和其他语言中发现的简单的旧 == ?

var a = 1.23;
    b = 1.230000001;

if(a === b) alert("equal?!");
Run Code Online (Sandbox Code Playgroud)

此代码不会产生警报,这意味着它可以像在 C/C++ 中一样工作。

Rya*_*yan 4

正如您所发现的,如果两种类型都是数字,==则 和的行为相同。===

在比较数字是否相等时,JavaScript 遵循 IEEE 754 标准。对于大多数用途来说,这与 C 的类型没有什么不同double。这意味着 JavaScript 不会你做任何精确检查。当需要时,您可以编写自己的代码来处理精度损失。


这回答了您的问题,但您提出了一个非常常见的误解!

JavaScript 数字是双精度数,因此 == 和 === 永远不应该按原样使用。

这背后的实际数学有点复杂。一旦掌握了,你就可以在精确检查方面获得一些余地。

考虑以下几点,这些都是有保证的事实

5 + 6 === 11
3 + 0.5 === 3.5
1.1 + 1 === 2.1
1.230000001 === 1.230000001
40 / 2 === 20
-0 === +0
Run Code Online (Sandbox Code Playgroud)

但是,根据精度,以下内容可能是正确的或错误的:

1.23 === 1.230000001
1.1 + 0.1 === 1.2
11 / 10 * 11 === 11 * 11 / 10
Run Code Online (Sandbox Code Playgroud)

为了使处理双精度数更容易,这些条件不会导致大范围浮点数的精度损失:

  • 不带小数部分的双精度数的加法、减法和乘法
  • 不带小数部分且可整除的双精度数除法
  • 将表示为分母 2, 4, 8, 16, ... 的分数的双精度数相加
  • 将任何双精度数乘以 0, 1, -1, 2, -2, 4, -4, 8, -8, ...
  • 将任何双精度数除以 1, -1, 2, -2, 4, -4, 8, -8, ...

最后,如果您想了解有关浮点数学的更多信息,请大量引用本文(但可能会因您的需要而过于详细):每个计算机科学家应该了解浮点运算的知识