存储方式
在js中数字都采用64位二进制数表示(IEEE754),格式如下:
- 一位的符号位
- 11位的指数位,为了减少负数对于表示的影响所以采用偏移量表示法来表示指数,由于指数有11位,所以需要偏移
2**(11 - 1) - 1 = 1023
, 所以实际的指数需要加上1023才等于内存中存储的数值。 - 52位的指数位,规范化数中,隐含了首位为1,非规范化数隐含了首位为0,所以在计算的时候实际有效的是53位。在js中同时存在规范化数,和非规范化数,当数字接近于0时使用非规范化数存储,因为这能保存更小的数值,其余数都采用规范化数的方式存储。
指数位全为0或者1具有特殊含义表示NaN或者Infinity,表示数时不会使用。
最小增量
个体对于群体而言终究是弱小的
对于每一个数都有自己的最小增量,同一个量级(指数位相同)的最小增量是相同的。Number.MAX_VALUE, js所能表示的最大值。那么Number.MAX_VALUE + 1就是Infinity吗?
1太小了,不足以被Number.MAX_VALUE所感知且JS引擎也无法表示出Number.MAX_VALUE + 1所以JS引擎认为Number.MAX_VALUE等于Number.MAX_VALUE + 1。要想修改某一个数A或者说要想某个数A能够感知到一个数B,那么这个数B必须大于等于数A的最小增量。Number.MAX_VALUE的值等于:
虽然上边的式子看不出Number.MAX_VALUE的指数是多少,但是这是最大值吗,所以指数位肯定是最大的,全0,全1有特殊作用,所以指数只能是1023,所以Number.MAX_VALUE的最小增量为
2**(1023-52)
, 其实就是最低位对这个数的影响。但是这个这是理论上,在浏览器环境中这个最小增量和理论值不一定相同,但是在理论值附近:
理论上来说,只有第一个为false,后面两个都应该为true才对,但是第二个的结果为false。暂时没有找到明确的理由。
四个值的计算方式
- Number.MAX_VALUE:符号位为1,指数位1111111110,不能全为0或者1,偏移1023,那么指数的计算值为2046 - 1023 = 1023,尾数全为1,包含隐含的1,那么结果为:
注意哈21024 - 2971一定要拆开,不然Infinity减任何数都为Infinity。
- Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER,最大/最小安全整数,由于尾数为52位,包括隐含的1,那么优秀位数就是53为,所以在不丢失精度的情况下,能够表示的最多整数就是
2**53 - 1
,最小整数就是-(2**53-1)
:
- Number.MIN_VALUE, 这个值采用的是非规范化数的方式进行存储的,二进制表示为:
1 00000000001 000…1, 计算式为:1 * 2 ** (1-1023) * 2**-52
逻辑与现实不符
希望实际不会遇到这种问题
最小值无限逼近0,不等于0.但是计算结果是相同的。