高级前端
js
【Q630】什么是安全整数,如何判断一个整数是安全整数

什么是安全整数,如何判断一个整数是安全整数

Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 648 (opens in a new tab)

Author 回答者: shfshanyue (opens in a new tab)

根据 MDN 的文档描述:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger (opens in a new tab)

一个安全整数是一个符合下面条件的整数:

  1. 可以准确地表示为一个IEEE-754双精度数字,
  2. 其IEEE-754表示不能是舍入任何其他整数以适应IEEE-754表示的结果。.

Number.MAX_SAFE_INTEGER 是最大安全整数,Number.isSafeInteger() 用来判断一个数值是否为安全整数。

而在安全整数之外,加减计算则会发生精度问题,如下:

Number.MAX_SAFE_INTEGER;
//=> 9007199254740991
 
Number.MAX_SAFE_INTEGER + 1;
//=> 9007199254740992
 
// 计算错误,结果应该是 9007199254740993
Number.MAX_SAFE_INTEGER + 2;
//=> 9007199254740992

而安全整数的问题,与 0.1+0.2 的问题类似。在 Javascript 中,整数被存储为双精度浮点数,而在整数大到一定程度后,就会导致精读失真。

如下,最大安全整数可以精准表示。以下截图使用 https://devtool.tech/double-type (opens in a new tab) 进行实时转换整数的 IEEE754 表示。

在双精度浮点数中,尾数位有 52 位,而最大安全整数为 2 ** 53 - 1,通过以下截图,也可以看做是 1.9999999999999998 * 2 ** (1075-1023)

但是最大安全整数加2,尾数位会溢出,导致该数值无法精准表示。

Author 回答者: Feahter (opens in a new tab)

自2003年以后,电脑普遍采用x86-64架构,而架构的数据单元的固定为64位(8字节) 64位双精度浮点数(double-precision 64-bit floating point format) 其中双精度浮点数是用来表示带有小数部分的实数 双精度浮点数最多有15或16位十进制有效数字,即53位二进制有效数字 IEEE-754规定 64位二进制存储单元由3部分组成 1+11+52 1是表示正负数 11是表示指数位置 52则是数据值位置 所以因为单位存储空间限制,安全整数的范围是1位正数加52位数据位 即53位二进制,超过只能溢出到指数位置存储,无法安全表示,所以安全整数的位数是 Number.MAX_SAFE_INTEGER.toString(2).length;

https://github.com/anjia/blog/issues/87 (opens in a new tab)