js 中整数的安全范围

358 阅读2分钟

安全整数指的是,在这个范围内的整数转化为二进制存储的时候不会出现精度丢失,能够被“安全”呈现的最大整数是 2^53 - 1, 即9007199254740991,在 ES6 中被定义为 Number.MAX_SAFE_INTEGER。最小整数是-9007199254740991,在 ES6 中 被定义为 Number.MIN_SAFE_INTEGER。

如果某次计算的结果得到了一个超过 JavaScript 数值范围的值,那么这个值会被自动转换为特殊的 Infinity 值。如果某次 计算返回了正或负的 Infinity 值,那么该值将无法参与下一次的计算。判断一个数是不是有穷的,可以使用 isFinite 函数 来判断。

JS中最大和最小安全整数为啥是2^53-1和-(2^53 - 1) ?

JS采用的是64位双精度浮点数来表示的,其中 1位符号位,11位阶码位(也称指数位),52位尾数位,而之所以称"安全",是指这些整数在这52位尾数位里都有一一对应的值,那按理来说应该是2^52 - 1 和 -(2^52-1),但是重点来了,计算机存储时,尾数都会默认首位为1,但是在写的时候不会表示出来(double和float的尾数都有这个特征, float 为 1位符号位,8位阶码位,23位尾数位)。

所以这个范围就扩展成2^53-1和-(2^53 - 1),注意安全整数和整数不是一个概念哦,安全是指值唯一,不会造成精度损失,你超过这个安全整数,然后相加减,都会造成精度损失

浮点数存储公式:

image.png

为啥是 E - 1023? 因为阶码位有11位,可表示数位 0 - (2^11 - 1), 也就是 0 - 2047,然后取中1023为中间位,向左为负,向右为正,  那为啥是 M + 1 ?因为尾数在存储时默认首位为1,所以存的时候,应该将首位真值去掉,再存储。

为啥 0.1 + 0.2 !== 0.3 ?

js浮点数相加减都会有精度问题,因为都会先将十进制数转成二进制数,然后以二进制形式相加减后,在转成十进制数进行比较

十进制小数转二进制小数, 都是乘以2 ,有整数则赋1,无整数则赋0,

二进制小数转十进制小数,是小数点后每增加一位,就将该位乘以 2^(负第几位)

例: 0b(0.001) = 0 * 2^(-1) + 0 * 2^(-2) + 1 * 2^(-3) = 0.125

0.1 = 0b(0.00011001100110011001100110011001100110011001100110011010)

0.2 = 0b(0.0011001100110011001100110011001100110011001100110011010)

0.1 + 0.2 = 0b(0.0100110011001100110011001100110011001100110011001100111) => 0.30000000000000004

所以 0.1 + 0.2 !== 0.3