首先,目前 js 的数字类型有两种:Number、BigInt。其中 bigint 是后面加 n,不讨论,可以看下相关知识。
number 类型都是双精度浮点型。
1、2^53 - 1
双精度浮点数能保存最大的“安全整数” 2^53 - 1,9007199254740991 为以下:
parseInt("11111111111111111111111111111111111111111111111111111",2) // 9007199254740991
双精度浮点数二进制存储形式:
sign 位 exponent 位 franction 位 52 位 隐藏位 1
0 10000110011 11111111111111111111111111111111111111111111111111111 1
2、2^53
当存储 9007199254740992(2^53) 为:
parseInt("100000000000000000000000000000000000000000000000000000",2)
双精度浮点数二进制存储形式:
sign 位 exponent 位 franction 位 52 位 隐藏位 1
0 10000110100 0000000000000000000000000000000000000000000000000000 1
3、结论:
从第 2^53 位开始,超出位被舍弃,这个时候,2^53+1===2^53。再过 N 个值,会出现每 4 个值里面都有 3 个值不精确;再过 M 个值,会出现每 2^K 个值里有 2^K-1 个值不精确;以此类推……
额外:这里尾数是 52 位,但是最大安全整数是 2^53 - 1,这个 53 是因为用上了隐藏位。
顺便说下 0.1+0.2 !== 0.3 的提示:计算机存储小数也是通过二进制存储,导致 2 的 n 次幂无法精确表示所有小数。
最后,推荐下我总结的文章:
https://www.yuque.com/dixdiydiz/qdjs/number