为什么JavaScript最大安全整数是2^53-1

12,259 阅读2分钟

复制来对 Number类型 相对官方的解释.

ECMAScript 中最有意思的数据类型或许就是 Number 了。Number 类型使用IEEE 754 格式表示整数和浮点值(在某些语言中也叫双精度值)。 ---红宝书

在 JavaScript 中, Number 是一种 定义为 64位双精度浮点型(double-precision 64-bit floating point format) (IEEE 754)的数字数据类型。 ---MDN

Number 类型使用IEEE 754 格式。

IEEE 754 格式

IEEE 754规定了四种表示浮点数值的方式:单精确度(32位)、双精确度(64位)、延伸单精确度(43比特以上,很少使用)与延伸双精确度(79比特以上,通常以80位实现)。

Number类型使用的便是其中的双精确度(64位)。

这张图就把结构说清了。

位置位数作用表示
0-5152尾数位原码表示
52-6211指数位移码表示
631符号位0,1

举个例子

  1. 十进制数值:10.25
  2. 转化为二进制 => 1010.01
  3. 规格化 => 1.01001 * 2^3
  4. 存储: 01001放在尾数位置,3放在指数位。指数位有11位,则移码是1023+3,为100...0010,移码参考这个IEEE754表示浮点数。整个表示为这样:

image.png

到现在一个数便表示出来了。

最大值

考虑能表示的最大值,就要看1.x2y1.x*2^y

在固定位数时候所能表示的最大值。

指数位 移码最大值为11位1,原码最大值为10位1(原码最高位表示符号位),则y最大为1023,x最大表示52位1。即1.1111...1乘以 2^1023,即2^1023*(2-2^-52) 这个值也就是 Number.MAX_VALUE 的大小

最大安全整数

什么叫最大安全整数?指的也就是这个常量Number.MAX_SAFE_INTEGER

现在考虑,我们看两个数2^53与2^53+1。

  • 2^53 我们尝试把它表示成二进制:1 53个0 ,规格化 1.0...00 * 2^53

  • 那2^53+1呢?我们尝试把它表示成二进制:1 52个0 1 ,标准化 1.0...01 * 2^53

问题来了,尾数都有53位,但只要52个空! 它的处理办法是 忽略第53位 ,因此这两个数在计算机中表示的结果一样!

2**53===2**53+1    //true

此时就不安全了。显而易见,在2^53-1之后的数中,只要指数相同,并且尾数前52位相同,则这个两个数数值相同。