你满溢JavaScript的号码类型的能力,看到§8.5 of the spec了解详情。这些ID将需要字符串。
IEEE-754双精度浮点数(JavaScript使用的数字种类)不能精确地表示全部数字(当然)。着名的,0.1 + 0.2 == 0.3
是错误的。这可能影响整数,就像影响分数一样;一旦您获得9,007,199,254,740,991(Number.MAX_SAFE_INTEGER
)以上,它就会启动。
超出Number.MAX_SAFE_INTEGER + 1
(9007199254740992
),IEEE-754浮点格式不能再代表每个连续的整数。 9007199254740991 + 1
是9007199254740992
,但是9007199254740992 + 1
是也9007199254740992
,因为9007199254740993
不能用格式表示。接下来可以是9007199254740994
。然后9007199254740995
不能,但9007199254740996
可以。
原因是我们已经用尽了位,所以我们不再有1位;最低位现在代表2的倍数。最终,如果我们继续前进,我们会失去那一点,只能以4的倍数工作。依此类推。
您的值是以及高于该阈值,因此它们会四舍五入到最接近的可表示值。
如果你好奇的位,这里发生的事情:一个IEEE-754二进制双精度浮点数有一个符号位,指数为11位(定义数的整体规模作为2的幂[因为这是一种二进制格式])和52位有效位(但格式非常聪明,它在52位中得到53位精度)。如何使用指数是复杂的(described here),但在非常模糊的术语,如果我们加上一个指数,有效数字的值加倍,因为指数用于2的幂(同样,在那里注意,这不是直接的,那里有聪明)。
那么让我们来看看价值9007199254740991
(又名Number.MAX_SAFE_INTEGER
):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
/ +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
// | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
// |/ |
0 10000110011 1111111111111111111111111111111111111111111111111111
= 9007199254740991 (Number.MAX_SAFE_INTEGER)
也就是说指数值,10000110011
,意味着我们每次添加一个到尾数时间,代表人数由1上升(中整数1,我们很早就失去了表示分数的能力)。
但是现在该有效数已满。要超过这个数字,我们必须增加指数,这意味着如果我们为有效数字加1,那么数字的值就会增加2,而不是1(因为指数应用于2,这个基数二进制浮点数):
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
/ +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
// | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
// |/ |
0 10000110100 0000000000000000000000000000000000000000000000000000
= 9007199254740992 (Number.MAX_SAFE_INTEGER + 1)
好吧,没关系,因为9007199254740991 + 1
是9007199254740992
反正。但!我们不能代表9007199254740993
。我们已经用尽了点儿。如果再加上仅1到尾数,它增加了2到值:
+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
/ +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
// | +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
// |/ |
0 10000110100 0000000000000000000000000000000000000000000000000001
= 9007199254740994 (Number.MAX_SAFE_INTEGER + 3)
格式只是不能再代表奇数为我们增加值,指数太大。
最后,我们再次耗尽有效位,必须增加指数,所以我们最终只能够表示4的倍数。然后是8的倍数。然后是16的倍数。等等。
感谢所有的快速有益的答案,我希望我可以标记所有3作为正式答案。 – Jaanus