什么是安全整数,如何判断一个整数是安全整数
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 648
Author 回答者: shfshanyue
根据 MDN 的文档描述:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Number/isSafeInteger
一个安全整数是一个符合下面条件的整数:
- 可以准确地表示为一个IEEE-754双精度数字,
- 其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 进行实时转换整数的 IEEE754 表示。
在双精度浮点数中,尾数位有 52 位,而最大安全整数为
2 ** 53 - 1
,通过以下截图,也可以看做是1.9999999999999998 * 2 ** (1075-1023)
但是最大安全整数加2,尾数位会溢出,导致该数值无法精准表示。
Author 回答者: Feahter
自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;