0.1+0.2!=0.3

众所周知,JavaScript在计算某些浮点数的运算时会出现精度的丢失,比如你在控制台输入0.1+0.2,得到的结果是0.30000000000000004而不是0.3,原因是什么?
世界上有两种人,懂二进制和不懂二进制的人
我们知道,计算机里所有的数据最终都是以二进制保存的,当然数字也一样。所以当计算机计算0.1+0.2的时候,实际上计算的是这两个数字在计算机里所存储的二进制,那么0.1在JavaScript里存储的二进制到底是多少?
我们先根据十进制转二进制的方法,把0.1转化为二进制是:0.0001100110011001100…(1100循环),然后把0.2转化为二进制是:0.00110011001100…(1100循环)。
我们发现,它们都是无限循环的二进制。显然,计算机当然不会用自己“无限的空间”去存储这些无限循环的二进制数字。那对于这类数据该怎么办?
JavaScript如何存储无限循环的二进制小数?
不同的语言可能会有不同的存储标准,JavaScript中所用的数字包括整数和小数,都只有一种类型就是Number,它的实现遵循IEEE 754标准,使用64位固定长度来表示,也就是标准的double双精度浮点数(相关的还有float 32位单精度),具体的双精度浮点数的存储方式这里不再赘述(可以看后面章节的详细描述),我们只需要知道,在二进制科学表示法中,双精度浮点的小数部分最多只能保留52位(比如1.xxx…*2^n,这里x最多保留52位)加上前面的1,其实就是保留53位有效数字,剩余的舍去,遵从“0舍1入”,那么0.1的二进制舍去之后就是:
0.00011001100110011001100110011001100110011001100110011010
复制代码同理我们得到0.2的舍去之后的二进制表示为:
0.0011001100110011001100110011001100110011001100110011010
复制代码二者相加得到:
0.00011001100110011001100110011001100110011001100110011010 +
0.0011001100110011001100110011001100110011001100110011010 =
0.0100110011001100110011001100110011001100110011001100111
复制代码我们把结果根据公式或者工具转为十进制:

可以看到结果正好为:0.30000000000000004。

注:大多数语言中的小数默认都是遵循 IEEE 754 的 float 浮点数,包括 Java、Ruby、Python,本文中的浮点数问题同样存在。

链接:https://juejin.im/post/5bd2f10a51882555e072d0c4

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值