JavaScript Numbers
Opened this issue · 5 comments
hushicai commented
JavaScript浮点数相关资料。
hushicai commented
双精度浮点数存储格式:
sign(符号): 用来表示正负号
exponent(指数): 用来表示次方数
mantissa(尾数): 用来表示精确度
符号
0代表数值为正,1代表数值为负。
指数
双精度浮点数在存储指数位时,会加上一个固定的偏移值。
IEEE 754标准规定该固定值为2^(e-1) - 1
,其中e为指数位的长度,即2^(11 - 1) - 1 = 1023
。
尾数
尾数一般要求规格化,把尾数处理到(0, 2)
区间内,这样可以省去小数点前的1
。
例子
例如0.1 转成二进制:
0.1.toString(2)
// "0.0001100110011001100110011001100110011001100110011001101"
科学计数法:
1.100110011001100... x 2^-4
我们自己算出来的是-4
,但实际计算机存储时,会加上偏移值,即E = -4 + 1023 = 1019
。
Number(1019).toString(2)
// "1111111011"
M 舍去首位的1,得到 100110011001100...,最终就是:
references
hushicai commented
安全整数
在(-2^53, 2^53)
范围内,所有的整数都有唯一的浮点数表示,这就是所谓的安全整数。
2^53
二进制表示:
1000000...000 (一个1,53个0)
科学计数法:
1.000000...000 x 2^53(小数点后53个0)
其实就相当于小数点往左移动了53位。
双精度表示法:
符号位:0,指数:53,尾数:1.000000...000 (小数点后52个0)
由于双精度浮点数的尾数位数限制,最后一位0丢失了,精度丢失了,所以不认为是一个安全整数
2^53 - 1
二进制表示:
11111111111111111111111111111111111111111111111111111(53个1)
科学计数法:
1.111111...111 x 2^52(小数点后52个1)
双精度表示法:
符号位:0,指数:52,尾数:1.111111....111 (小数点后52个1)
2^53 - 2
二进制表示:
11111111111111111111111111111111111111111111111111110(52个1,一个0)
科学计数法:
1.111111...1110 x 2^52(小数点后51个1,一个0)
双精度表示法:
符号位:0,指数:52,尾数:1.111111....110 (小数点后51个1,一个0)
以此类推,以上范围内的整数都可以由一个唯一的浮点数表示。
如果超出了以上范围,存储就可能不唯一了,例如2^53 + 1
。
2^53 + 1
二进制表示:
1000000...001 (一个1,52个0,一个1)
科学计数法:
1.000000...001 x 2^53(小数点后52个0,一个1)
双精度表示法:
符号位:0,指数:53,尾数:1.000000...000 (小数点后52个0)
由于双精度浮点数的尾数位数限制,最后一位1要丢掉。
所以实际上2^53 + 1
和2^53
的存储是一样的:
Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
整数和浮点数不再一一对应,所以就不安全了。