首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >for(var i = 0; 1 / i> 0; i ++){}这个'for'循环是否停止,为什么?为什么不呢?

for(var i = 0; 1 / i> 0; i ++){}这个'for'循环是否停止,为什么?为什么不呢?
EN

Stack Overflow用户
提问于 2018-03-26 06:50:03
回答 2查看 0关注 0票数 0

这个for循环是否会停止?

代码语言:javascript
复制
for (var i=0; 1/i > 0; i++) {
}

如果是这样,何时和为什么?

EN

回答 2

Stack Overflow用户

发布于 2018-03-26 15:00:29

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

原因如下:

  1. 最初,什么时候i是这样0,条件1/i > 0是真的,因为在JavaScript中,1/0Infinity,并且Infinity > 0是真的。
  2. 之后,i将会增加并且长时间继续增长为一个正整数值(再进行9,007,199,254,740,991次迭代)。在所有这些情况下,1/i都会保留下来> 0(尽管最终的值1/i会变得非常小),所以循环会继续到达并包括i达到该值的循环Number.MAX_SAFE_INTEGER
  3. JavaScript中的数字是IEEE-754双精度二进制浮点数,它是一种非常紧凑的格式(64位),它提供了快速计算和广泛的范围。它通过将数字存储为一个符号位,一个11位指数和一个52位有效位数(尽管通过巧妙性实际上得到53位精度)来完成此操作。它是二进制的(基数2)浮点数:有效数(加上一些聪明)给了我们值,指数给出了数的大小。 当然,只有很多重要的位,并不是每个数字都可以被存储。这里是数字1,和1之后,该格式可以存储下一个最高的数,1 + 2 -52 ≈1.00000000000000022,和之后的下一个最高的是1 + 2×2 -52 ≈1.00000000000000044: + ------------------------------------------------- --------------签位 / + ------- + ---------------------------------------- --------------指数 / / | + ------------------------------------------------- + - 有意义 / / | / | 0 01111111111 0000000000000000000000000000000000000000000000000000 = 1 0 01111111111 0000000000000000000000000000000000000000000000000001 ≈ 1.00000000000000022 0 01111111111 0000000000000000000000000000000000000000000000000010 ≈ 1.00000000000000044 注意从1.00000000000000022跳到1.00000000000000044; 没有办法存储1.0000000000000003。这也可能发生在整数上:Number.MAX_SAFE_INTEGER(9,007,199,254,740,991)是格式可以容纳的最高正整数值,i并且i + 1都可以精确地表示(spec)。9,007,199,254,740,991和9,007,199,254,740,992都可以表示,但下一个整数9,007,199,254,740,993不能; 9,007,199,254,740,992之后的下一个整数是9,007,199,254,740,994。这里是位模式,注意最右边的(最不重要的)位: + ------------------------------------------------- --------------签位 / + ------- + ---------------------------------------- --------------指数 / / | + ------------------------------------------------- + - 有意义 / / | / | 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)无法存储 0 10000110100 0000000000000000000000000000000000000000000000000001 = 9007199254740994(Number.MAX_SAFE_INTEGER + 3) 请记住,格式是基数2,并且指数的最低有效位不再是小数; 它的值为2.它可以关闭(9,007,199,254,740,992)或(9,007,199,254,740,994); 所以在这一点上,即使在整数(整数)范围内,我们也开始失去精度。这对我们的循环有影响!
  4. 完成i = 9,007,199,254,740,992循环后,i++再给我们...... i = 9,007,199,254,740,992; 没有改变i,因为下一个整数不能被存储,并且计算结束。i如果我们这样做会改变i += 2,但i++不能改变它。所以我们已经达到了稳定状态:i永远不会改变,循环也不会终止。

以下是各种相关计算:

代码语言:javascript
复制
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
票数 0
EN

Stack Overflow用户

发布于 2018-03-26 16:32:07

该条件1/i > 0将始终评估为真:

  • 最初,它因为是真实的1/0评估,以InfinityInfinity > 0为真
  • 它保持真实,因为1/i > 0对所有人都是真的i < Infinityi++永远不会到达Infinity

为什么i++永远不会到达Infinity?由于Number数据类型的精确度有限,因此存在以下值i + 1 == i

代码语言:javascript
复制
9007199254740992 + 1 == 9007199254740992 // true

一旦i达到该值(对应于),它将保持不变。Number.MAX_SAFE_INTEGER+ 1i++

因此我们有一个无限循环。

附录:

为什么9007199254740992 + 1 == 9007199254740992

JavaScript的Number数据类型实际上是一个64位IEEE 754双精度浮点数。每个Number分解和存储为三部分:1位符号,11位指数和52位尾数。它的值是-1 符号 ×尾数×2 指数。

如何9007199254740992代表?由于1.0×2 53或二进制:

在这里输入图像描述
在这里输入图像描述

增加尾数的最低位,我们得到下一个更高的数字:

在这里输入图像描述
在这里输入图像描述

该号码的值为1.00000000000000022 ...×2 53 = 9007199254740994

那是什么意思?Number可以是900719925474099 2或900719925474099 4,但两者之间没有任何关系。

现在,我们选择哪一个代表900719925474099 2 + 1?在IEEE 754舍入规则给出了答案:900719925474099 2

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100004310

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档