如果有足够的时间,此循环会结束吗?
for (let i = 0; 1 / i > 0; i++) {} // js code [0]
我想i
到达Number.POSITIVE_INFINITY
时会这样,但是不知道如何测试。
修改:
for (let i = 0; 1 / i > 0; i += k) {} // js code [1]
使 js代码[1] 完成的最小正数k
是多少? (至少k = 1e304
会)
让我们假设问题1的答案为K
,大于K
的数字是否可以保证 js代码[1] 的完成?
答案 0 :(得分:6)
不,它永远不会结束,因为在高数字下,数字精度会失败。例如,将1
添加到1e16
会得到一个数字,该数字也等于1e16
-超过某一点,它将永远不会进行:
console.log((1e16 + 1) === 1e16);
这是9007199254740992
。 JavaScript的MAX_SAFE_INTEGER
是9007199254740991
。将一个加到9007199254740991
会得到9007199254740992
,但是将一个加到9007199254740992
会得到相同的数字9007199254740992
:
console.log(9007199254740991 + 1 === 9007199254740992);
console.log(9007199254740992 + 1 === 9007199254740992);
您在Infinity
附近到达1.7e308
。
答案 1 :(得分:2)
k
完成的最小正数for (let i = 0; 1 / i > 0; i += k) {}
是2 970 +2 918 ,它是9979201547673601274109728689479476941425536662556495940151194794704206738934049246746743498432906272845051601607544504207607607407697406946786576546946546715476546946546946546946546946546576546946546546546546546546546546546546546546546546546546546786546546716576545474576546546546546546546546546546546546546546546546576576546546546546546546546546546546546546546572亿英镑
JavaScript是ECMAScript的方言,它指定它使用64位(二进制)IEEE-754浮点格式,并具有从最近到最近的关系。在这种格式中,最大的有限数在从2 1023 (包括)到2 1024 (不包括)的binade中。由于浮点数的有效位(分数部分)具有53位,因此这些数的最低有效位的位置值为2 1023-52 = 2 971 。这称为最低精度单位(ULP)。 (ULP是浮点数指数的函数;它随该数字成比例缩放。)
计算i+k
时,结果将四舍五入到最接近的可表示数字。如果k
小于i
的½ULP,则最接近i
+ k
的数学值的可表示数为i
,因此不会发生变化当执行i = i+k
时。如果k
恰好是i
的½ULP,则i
+ k
的数学值恰好在i
与下一个可表示的值之间。根据四舍五入原则,如果i
的低位为零,则四舍五入;如果为k
,低位为四舍五入。因此,如果i = i+k
恰好是最大有限浮点数的½ULP,则k
不会对其中的一半产生任何变化,因此循环不会继续进行。
如果i
超过i
的½ULP,则k
+ i
的数学值比{{1 }},结果是i
加一个ULP,所以循环继续进行。 (在特殊情况下,i
是可表示的最大有限值,加法将产生无穷大,由于1 / i
将为零,因此该循环将终止循环。)
如上所述,最大值的ULP为2 971 。 ½ULP是2 970 。我们需要k
使其比此值大尽可能小,因此我们想为其添加一个ULP。 (一个最大规模的ULP,而不是最大数量的ULP。)2 970 的ULP是2 970-52 = 2 918
因此,导致循环终止的最小正数k
是2 970 +2 918 。