string(21) "{"docs":[],"count":0}" array(2) { ["docs"]=> array(0) { } ["count"]=> int(0) } js浮点数计算失精原理 - 爱码网

首先,我们知道js中的数字都是双精度的浮点数,在进行计算时,计算机会把十进制数转换成64位二进制,这个过程可能会导致精度丢失。

计算机存储是按照IEEE754标准来把64位分成3个区域

js浮点数计算失精原理

十进制浮点数转换成二进制,然后转换成指数格式,由于尾数部分只能保留52位,第53位0舍1入,所以截取52位导致精度丢失。

以0.1和0.5为例,0.1损失精度,0.5不损失精度

0.1转换成二进制:

0.00011001100110011001100110011001100110011001100110011001100110011001.....无限循环

然后转换成科学计数法表示,右移小数点移动4位,使小数点前的数字是1,变成:

1.1001100110011001100110011001100110011001100110011001100110011001.....无限循环 * 2 ^ -4

然后转换成IEEE754标准:

符号位是0代表正数,

上面得到的指数是-4,所以-4+1023=1019转成二进制,所以指数位就是01111111011

然后截取小数点后52位(0舍1入)放入尾数位,所以尾数位为:

1001100110011001100110011001100110011001100110011010

所以0.1的计算机存储为:

0011111110111001100110011001100110011001100110011001100110011010

由于截取52位导致了后续数据的丢失,也就导致精度丢失。


而0.5之所以不会丢失精度,是因为0.5转为二进制:0.1000,右移小数点移动1位,使小数点前数字是1,变成:1.00 * 2^-1,指数是-1,所以-1+1023=1022转成二进制指数位就是01111111110,所以0.5的计算机存储为:

0011111111100000000000000000000000000000000000000000000000000000,因为小数点后都是0,所以截取52位没有数据丢失,所以没有精度丢失。


关于为什么偏移量是1023,而不是11位能表示的最大范围2048(0~2047),是因为指数有正有负,所以能表示的范围是-1023~1024,所以偏移量是:

(11位表示的最大值)2047-(正指数的最大值)1024 = 1023,这样指数部分的值就都是无符号的正数值,便于比较数的大小。


特殊值:

指数位全0,根据符号位,这个数表示+0或-0;

指数位全1,尾数位全0,根据符号位,这个数表示+∞和-∞;

指数位全1,尾数位不是全0,这个数表示非数值NaN;


以上!

相关文章: