带着疑问出发:为什么最大表示2^53? 为什么9007199254740992 === 9007199254740993?
1、js中number 的存储
双精度浮点数
JS中的Number是以双精度浮点数的形式计算的,双精度浮点数总共有8个字节(byte),每字节有8比特(bit-位),即 8bit/byet,所以总共占位64位。
2、number在计算机中的存储
2.1 科学计数法
X = a*2^e,e代表位数,可为正(大于1),可为负(小于1)
举例:
a、27.0表示成二进制为:11011.0 用科学计数法表示为 1.10110 * 2^4
b、0.625表示成二进制:0.101 用科学计数法表示为 1.01∗2^−1 1.01 * 2^-1
2.2 在计算机中的存储
根据IEEE754的标准,双精度浮点数中的占位分为3个部分:符号位、指数部分、尾数部分
-
符号位置:1位。0表示负数,1表示正数
-
指数部分:11位。
公式:e+指数偏移量(1023)
e可以为正,可以为负数。
所以按照道理指数部分表示的二进制精度范围为:
a、最小:1023 + (-1023) = 0 ,即0.00...001(小数点后1023位)
b、最大:1023 + 1025 = 2^11,即111...111(共1025个1)
超出展示:Infinity
-
尾数部分:52位。
3、结论:
3.1、最大就是2^53 - 1
十进制:9007199254740991;二进制:1 1111111111111111111111111111111111111111111111111111 长度:53;尾数部分:52位
3.2、为什么2^53 可以表示
十进制:9007199254740992;二进制:1 0000000000000000000000000000000000000000000000000000 0 长度:54; 尾数部分:53位
虽然只能表示到2^53 - 1,但是超出未必失去精度
4、失去精度是偶现的原因
原因是超出位数的二进制类十进制的“四舍五入”。十进制的四舍五入是以5为分界线,离哪边进往哪边靠近。
应用到在二进制的单个位数的舍入时,0很明显要舍去,但是1距离前后长度都是1,该如何取舍?
4.1 IEEE754规范的舍入方案
“损失的精度最小"原则
- 首先判断精度损失(优先级最高),向上和向下都计算,精度损失最小者获胜,也就是"最近"原则.
- 如果距离相等(即精度损失相等),那么将执行偶数判断,偶数胜出.
举例:
1.011 01 保留 3位小数是 1.011
1.01101 101 保留4位小数是1.01110
1.0110 1 保留 4位小数是1.0110 (偶数胜出)
参考文章:
1、js精度丢失问题