查看原文
其他

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

CSDN App AI科技大本营 2019-10-30


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

  

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

 

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

             

             

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

 

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

 

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

 

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

 

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

 

             

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

             

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

 

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

 

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

 

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

              

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

 

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


             

 

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

               

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

              

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


             

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

 

数字0.1最终表示为:

              

相似地,0.2被表示为:

              

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

              

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

              

这就是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 折票开售,数量有限,扫码购买,先到先得!


推荐阅读

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

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存