关于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

  • 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 规范:

  1. 先把Number转成二进制科学计数法表示;
  2. 然后用64位bit存储二进制科学计算法的相关参数。

64位bit分为三个部分:

  • 符号位S:第 1 位是正负数符号位(sign),0代表正数,1代表负数
  • 指数位E:中间的 11 位存储指数(exponent),用来表示次方数
  • 尾数位M:最后的 52 位是尾数(mantissa),超出的部分自动进一舍

关于JavaScript中Number整数最大长度的一个疑问
实际数字就可以用以下公式来计算:
关于JavaScript中Number整数最大长度的一个疑问
比如:十进制数字4.5转成二进制就是 100.1,二进制的科学计数法表示就是1.001*2^2
此时M = 1001,但是因为二进制科学计数法的尾数M的第一位固定的1,所以可以直接省去(这样可以节省一个bit,导致M最多可以表示53位),即最终M = 001

  1. 为什么Number的最大整数是2 ** 53 -1呢?
    整数需要连续性,所以表示整数时不能使用指数位E区域,只有尾数M区域可表示连续的数据,上面说了其实M最多可以表示53位。所以最大的安全整数是2 ^ 53 -1

  2. Array索引既然是整数,那它的最大索引为什么不是2 ** 53 - 1
    JS语言中数组的索引最大就是2^32 -1。就当做语言规范吧,背后的原因不清楚。除了数组索引,还有其他的地方采用32bit整数:

    • 位运算
    • setTimeout/setIntervaldelay参数也是必须是32整数

  3. 导致我有这种疑惑的根本原因在哪儿呢?

刨根问底呗。

告诉你一个小秘密:

Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2

以上是 关于JavaScript中Number整数最大长度的一个疑问 的全部内容, 来源链接: utcz.com/a/66997.html

回到顶部