关于JavaScript中Number整数最大长度的一个疑问
业务背景
一直以来对Number的最大最小值都没有透彻的理解清楚,在开发过程中也从来没有遇到过这种极限情况
可是最近在刷红宝书第4版的时候,又遇到这个概念.所以想透彻的搞清楚一下
关于这个概念我的理解
书上的概念
Number
对象是采用64位存储的,即8个字节 * 8位 = 64位- 操作符在操作Number类型时,实际是操作的32位(位运算那一节介绍的)
- 在底层再把32位转换成64位进行处理
我的结论
- 最大的整数就是2的32次方减1
- 即
2 ** 32 - 1
- 书上在介绍数组索引时也能佐证,因为数组的索引是整数,最大的索引就是
2 ** 32 - 1
即4294967295
我的疑问
可是在开发过程中经常会遇到这样一个问题,JAVA
侧返回的订单编号或用户ID都整型,在Web
侧会出现后面2位超出JavaScript
整数取值范围
如下:
java = 123456789012345678; // 一共18个数js = 123456789012345600; // 一共16个数外加2个0
在新的ECMAScript
规范中也添加了1个Number常量最大安全整数Number.MAX_SAFE_INTEGER
- 这个里面的最大整数和上面的一样,是16个数
- 即2的53次方-1
2 ** 53 - 1
问题
为什么Number的最大整数是
2 ** 53 -1
呢?- 如果说是64位存储的话,为什么不是
2 ** 64 -1
呢. - 即使是去掉一个符号位,应该也是
2 ** 63 -1
呀
- 如果说是64位存储的话,为什么不是
- Array索引既然是整数,那它的最大索引为什么不是
2 ** 53 - 1
呢 导致我有这种疑惑的根本原因在哪儿呢?
- 是因为没有计算机基础功能?
- 还是没有基本的逻辑思维能力?
回答
Number,遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 位,其中1位用来表示符号位,11位用来表示指数,剩下52位表示尾数,就是这个Number.MAX_SAFE_INTEGER,又称为最大安全数,其值为2^53 -1,大于 9007199254740992 的可能会丢失精度
数组的最大长度是2的32次方减1,这个不是指数组只能存2^32-1位数据,也不是说数组的下标最大值就是2^32-1,而是指数组的length属性最大值为2^32-1。
ECMAScript 标准约定number数字需要被当成 64 位双精度浮点数处理,但事实上,一直使用 64 位去存储任何数字实际是非常低效的,所以 JavaScript 引擎并不总会使用 64 位去存储数字,引擎会在内部采用其他内存表示方式,如 32 位。
因为只有52位用来存有效数字,有一位放符号位,有11位放指数
前面都说的差不多了,总结下来就是 Number
遵循 IEEE 754 规范:
- 先把
Number
转成二进制科学计数法表示; - 然后用64位bit存储二进制科学计算法的相关参数。
64位bit分为三个部分:
- 符号位S:第 1 位是正负数符号位(sign),0代表正数,1代表负数
- 指数位E:中间的 11 位存储指数(exponent),用来表示次方数
- 尾数位M:最后的 52 位是尾数(mantissa),超出的部分自动进一舍
实际数字就可以用以下公式来计算:
比如:十进制数字4.5
转成二进制就是 100.1
,二进制的科学计数法表示就是1.001*2^2
。
此时M = 1001
,但是因为二进制科学计数法的尾数M
的第一位固定的1
,所以可以直接省去(这样可以节省一个bit,导致M
最多可以表示53位),即最终M = 001
。
- 为什么Number的最大整数是
2 ** 53 -1
呢?
整数需要连续性,所以表示整数时不能使用指数位E
区域,只有尾数M
区域可表示连续的数据,上面说了其实M
最多可以表示53位。所以最大的安全整数是2 ^ 53 -1
Array索引既然是整数,那它的最大索引为什么不是
2 ** 53 - 1
呢
JS语言中数组的索引最大就是2^32 -1
。就当做语言规范吧,背后的原因不清楚。除了数组索引,还有其他的地方采用32bit整数:- 位运算
setTimeout/setInterval
的delay
参数也是必须是32整数
- 导致我有这种疑惑的根本原因在哪儿呢?
刨根问底呗。
告诉你一个小秘密:
Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2
以上是 关于JavaScript中Number整数最大长度的一个疑问 的全部内容, 来源链接: utcz.com/a/66997.html