多数编程语言里的0.1+0.2≠0.3?

640?wx_fmt=jpeg

作者 | Parul Malhotra
译者 | Raku
出品 | AI科技大本营(ID:rgznai100)

  

我们从小就被教导说0.1+0.2=0.3,但是在奇妙的计算机编程世界里面,事情变得不一样了。

 

我最近在用JavaScript编程,正在阅读数据类型的时候,我注意到0.1+0.2不等于0.3的奇怪现象。我求助于Stack Overflow并找到了几条有帮助的信息,让我们来看一下:

       640?wx_fmt=png      

       640?wx_fmt=png      

经过大量的调查与数学研究,我得出结论:这并不是一个错误,而是数学——浮点运算。让我们进一步探索,去了解这个现象后面到底发生了什么。

 

现象描述:0.1 + 0.2 = 0.30000000000000004 是怎么发生的?

 

当你使用Java或者C编程的时候,你一定会意识到不同的数据类型用来存储不同的值,我们在前面的讨论中考虑的两种数据类型是整型与浮点型。

 

整形存储整数,浮点型存储小数。

 

在我们继续探索之前,让来理解一个小概念:以计算为目的,数字是如何被表示的?非常小与非常大的数字经常使用科学计数法表示,它的公式是:

 

       640?wx_fmt=png      

而且,当一个数字在使用科学计数法表示的时候,它会被归一化成小数点前一个非零的十进制数字的形式,例如,0.0005606在用科学计数法表示并归一化后,它被表示为:

       640?wx_fmt=png      

Significant 是不包含零的有效数字的数目,base表示所使用的进制——在这里是十进制,exponent 表示小数点需要向左或向右移动才能正确表示的位置数。

 

现在,有两种显示浮点数的方法:单精度与双精度。单精度使用32位,而双精度使用64位进行浮点运算。

 

不像其它编程语言,JavaScript没有定义不同类型的数字数据类型,而且始终遵循国际IEEE 754标准将数字存储为双精度浮点数。

 

这种格式以64位存储数字,其中数字(小数)存储在第0到51位,指数存储在第52到62位,符号存储在第63位中。

       640?wx_fmt=png       

让我们以IEEE754标准表示64位中的0.1。

 

第一步是将十进制的0.1转换成等价的二进制数。为此,我们先将0.1乘以2,然后将小数点前的数字分开,以得到二进制等价值。

       640?wx_fmt=png      

 

对于64位重复此操作,我们将按升序排列它们以获取尾数,根据双精度标准,我们将把其四舍五入为52位。

       640?wx_fmt=png        

用科学计数法表示它并将其四舍五入到前52位将产生:

       640?wx_fmt=png       

尾数部分已准备就绪,现在,对于指数使用以下计算:

       640?wx_fmt=png      

在这里,11表示将用于指数的64位表示的位数,而-4表示科学计数法的指数。

 

数字0.1最终表示为:

       640?wx_fmt=png       

相似地,0.2被表示为:

       640?wx_fmt=png       

在使两者的指数相同之后将两者相加会得到:

       640?wx_fmt=png       

当以浮点表示时,它将变为:

       640?wx_fmt=png       

这就是0.1+0.2在计算机二进制中的表示。

 

把该二进制数转换回十进制小数,就得到了0.30000000000000004。

 

这就是隐藏在0.1 + 0.2 = 0.30000000000000004背后的原因。

 

原文链接:

https://medium.com/better-programming/why-is-0-1-0-2-not-equal-to-0-3-in-most-programming-languages-99432310d476


(*本文为 AI科技大本营翻译文章, 载请微 信联系 1092722531


精彩推荐


2019 中国大数据技术大会(BDTC)再度来袭!豪华主席阵容及百位技术专家齐聚,15 场精选专题技术和行业论坛,超强干货+技术剖析+行业实践立体解读,深入解析热门技术在行业中的实践落地。

即日起,限量 5 折票开售,数量有限,扫码购买,先到先得!

640?wx_fmt=jpeg

推荐阅读

640?wx_fmt=png

你点的每个“在看”,我都认真当成了喜欢

  • 68
    点赞
  • 130
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值