这个for循环会停止吗?

for (var i=0; 1/i > 0; i++) {
}
如果是这样,什么时候以及为什么?有人告诉我它停止了,但是我没有理由这么做。
更新日期
作为调查的一部分,我写了一篇冗长而详尽的文章,解释了幕后工作-Here is what you need to know about JavaScript’s Number type

最佳答案

(我不喜欢meta内容,但是:gotnull'sle_m's答案都是正确且有用的。它们本来就是,更是如此,所以在发布此社区Wiki后所做的编辑中更是如此。由于进行了这些修改,该CW在很大程度上消失了,但是它仍然有用,因此...。另外:虽然只列出了几位作者,但许多其他社区成员对已折叠并整理的评论也有很大帮助(这不只是名称上的CW。)

在正确实现的JavaScript引擎中,循环不会停止。 (引擎的宿主环境最终可能会终止它,因为它是无止境的,但这是另一回事。)

原因如下:

  • 最初,当i0时,条件1/i > 0为true,因为在JavaScript中,1/0Infinity,而Infinity > 0为true。
  • 之后,i将递增,并在很长一段时间内继续增长为正整数值(再进行9,007,199,254,740,991次迭代)。在所有这些情况下,1/i仍将是> 0(尽管1/i的值实际上会使很小!),因此循环继续进行,直到i达到值Number.MAX_SAFE_INTEGER的循环为止。
  • JavaScript中的
  • 数字是IEEE-754 double 二进制浮点,相当紧凑的格式(64位),可提供快速计算和广泛的范围。它通过将数字存储为符号位,11位指数和52位有效数字来实现此目的(尽管通过聪明,它实际上获得了53位精度)。它是二进制(以2为底)的浮点数:有效数字(加上一些技巧)给我们提供了值,指数给了我们数值的大小。

    自然,只有这么多的有效位,所以不能存储每个数字。这是数字1,格式可以存储的数字1之后的下一个最高数字1 + 2-52≈1.00000000000000022,该数字之后的第二个最高数字1 + 2×2-52≈1.00000000000000044:
       +--------------------------------------------------------------- sign bit
      / +-------+------------------------------------------------------ exponent
     / /        |  +-------------------------------------------------+- significand
    / /         | /                                                  |
    0 01111111111 0000000000000000000000000000000000000000000000000000
                    = 1
    0 01111111111 0000000000000000000000000000000000000000000000000001
                    ≈ 1.00000000000000022
    0 01111111111 0000000000000000000000000000000000000000000000000010
                    ≈ 1.00000000000000044
    

    Note the jump from 1.00000000000000022 to 1.00000000000000044; there's no way to store 1.0000000000000003. That can happen with integers, too: Number.MAX_SAFE_INTEGER (9,007,199,254,740,991) is the highest positive integer value that the format can hold where i and i + 1 are both exactly representable (spec). Both 9,007,199,254,740,991 and 9,007,199,254,740,992 can be represented, but the next integer, 9,007,199,254,740,993, cannot; the next integer we can represent after 9,007,199,254,740,992 is 9,007,199,254,740,994. Here are the bit patterns, note the rightmost (least significant) bit:

       +--------------------------------------------------------------- sign bit
      / +-------+------------------------------------------------------ exponent
     / /        |  +-------------------------------------------------+- significand
    / /         | /                                                  |
    0 10000110011 1111111111111111111111111111111111111111111111111111
                    = 9007199254740991 (Number.MAX_SAFE_INTEGER)
    0 10000110100 0000000000000000000000000000000000000000000000000000
                    = 9007199254740992 (Number.MAX_SAFE_INTEGER + 1)
    x xxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                      9007199254740993 (Number.MAX_SAFE_INTEGER + 2) can't be stored
    0 10000110100 0000000000000000000000000000000000000000000000000001
                    = 9007199254740994 (Number.MAX_SAFE_INTEGER + 3)
    

    Remember, the format is base 2, and with that exponent the least significant bit is no longer fractional; it has a value of 2. It can be off (9,007,199,254,740,992) or on (9,007,199,254,740,994); so at this point, we've started to lose precision even at the whole number (integer) scale. Which has implications for our loop!

  • After completing the i = 9,007,199,254,740,992 loop, i++ gives us ... i = 9,007,199,254,740,992 again; there's no change in i, because the next integer can't be stored and the calculation ends up rounding down. i would change if we did i += 2, but i++ can't change it. So we've reached steady-state: i never changes, and the loop never terminates.

  • Here are the various relevant calculations:

    if (!Number.MAX_SAFE_INTEGER) {
      // Browser doesn't have the Number.MAX_SAFE_INTEGER
      // property; shim it. Should use Object.defineProperty
      // but hey, maybe it's so old it doesn't have that either
      Number.MAX_SAFE_INTEGER = 9007199254740991;
    }
    var i = 0;
    console.log(i, 1/i, 1/i > 0); // 0, Infinity, true
    i++;
    console.log(i, 1/i, 1/i > 0); // 1, 1, true
    // ...eventually i is incremented all the way to Number.MAX_SAFE_INTEGER
    i = Number.MAX_SAFE_INTEGER;
    console.log(i, 1/i, 1/i > 0); // 9007199254740991 1.1102230246251568e-16, true
    i++;
    console.log(i, 1/i, 1/i > 0); // 9007199254740992 1.1102230246251565e-16, true
    i++;
    console.log(i, 1/i, 1/i > 0); // 9007199254740992 1.1102230246251565e-16, true (no change)
    console.log(i == i + 1);      // true

    关于javascript - 这个 'for'循环会停止吗,为什么/为什么不呢? for(var i = 0; 1/i> 0; i++){},我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37827073/

    10-09 17:48