![2c7b21988295cba90b93780265ec8ae4.png](https://i-blog.csdnimg.cn/blog_migrate/f8e0f7c707e6a3842f462a27ef4911cd.jpeg)
作者 | Parul Malhotra
译者 | Raku
出品 | AI科技大本营(ID:rgznai100)
我们从小就被教导说0.1+0.2=0.3,但是在奇妙的计算机编程世界里面,事情变得不一样了。
我最近在用JavaScript编程,正在阅读数据类型的时候,我注意到0.1+0.2不等于0.3的奇怪现象。我求助于Stack Overflow并找到了几条有帮助的信息,让我们来看一下:
![287a93b0dbd64a07b512f670ba383ed2.png](https://i-blog.csdnimg.cn/blog_migrate/882e1be8099e5c76657a7a041485eb9f.jpeg)
![22e056afa93ffce38285eec2c71dc841.png](https://i-blog.csdnimg.cn/blog_migrate/969dac9a82d2d64373982717be3a384a.jpeg)
经过大量的调查与数学研究,我得出结论:这并不是一个错误,而是数学——浮点运算。让我们进一步探索,去了解这个现象后面到底发生了什么。
现象描述:0.1 + 0.2 = 0.30000000000000004 是怎么发生的?
当你使用Java或者C编程的时候,你一定会意识到不同的数据类型用来存储不同的值,我们在前面的讨论中考虑的两种数据类型是整型与浮点型。
整形存储整数,浮点型存储小数。
在我们继续探索之前,让来理解一个小概念:以计算为目的,数字是如何被表示的?非常小与非常大的数字经常使用科学计数法表示,它的公式是:
![d1b636e2acbc88fb4f5f2036d2ccd03c.png](https://i-blog.csdnimg.cn/blog_migrate/02f29b333f8fe4c53ff7d2be40c2907b.jpeg)
而且,当一个数字在使用科学计数法表示的时候,它会被归一化成小数点前一个非零的十进制数字的形式,例如,0.0005606在用科学计数法表示并归一化后,它被表示为:
![83040443c0037a1fad67850dc295e839.png](https://i-blog.csdnimg.cn/blog_migrate/117df1ef659d8b9aed38ac7f9f6d9484.jpeg)
Significant 是不包含零的有效数字的数目,base表示所使用的进制——在这里是十进制,exponent 表示小数点需要向左或向右移动才能正确表示的位置数。
现在,有两种显示浮点数的方法:单精度与双精度。单精度使用32位,而双精度使用64位进行浮点运算。
不像其它编程语言,JavaScript没有定义不同类型的数字数据类型,而且始终遵循国际IEEE 754标准将数字存储为双精度浮点数。
这种格式以64位存储数字,其中数字(小数)存储在第0到51位,指数存储在第52到62位,符号存储在第63位中。
![fd2c44c3b15a24aa03647c90efb81a92.png](https://i-blog.csdnimg.cn/blog_migrate/6c593e7d3cf3c0a9917e75b72ed55506.jpeg)
让我们以IEEE754标准表示64位中的0.1。
第一步是将十进制的0.1转换成等价的二进制数。为此,我们先将0.1乘以2,然后将小数点前的数字分开,以得到二进制等价值。
![39ebf2c93fea7762d93ae7346aefc20a.png](https://i-blog.csdnimg.cn/blog_migrate/5378b1d2c58a3412a181164c60b1ebc9.jpeg)
对于64位重复此操作,我们将按升序排列它们以获取尾数,根据双精度标准,我们将把其四舍五入为52位。
![552b5f0d0f77421dec4219e0763a7d8b.png](https://i-blog.csdnimg.cn/blog_migrate/f1436c317789bfd87bc5a124788a3599.jpeg)
用科学计数法表示它并将其四舍五入到前52位将产生:
![5f13c35d8fdf3fcbde9ab2ca24051193.png](https://i-blog.csdnimg.cn/blog_migrate/2c493155f51923108b1a3e45fcf7003c.jpeg)
尾数部分已准备就绪,现在,对于指数使用以下计算:
![6b0d8f1378301f3973e45d56eff1a10b.png](https://i-blog.csdnimg.cn/blog_migrate/5aaeda8fdfaf94ebe443c600c366c136.jpeg)
在这里,11表示将用于指数的64位表示的位数,而-4表示科学计数法的指数。
数字0.1最终表示为:
![c29ff4d5c37407690b67942fcda67306.png](https://i-blog.csdnimg.cn/blog_migrate/2d5e57c4b5f37dffeb6e584f3398fd56.jpeg)
相似地,0.2被表示为:
![3f5ebbd3cd3b20b2b4c1c119aed011a2.png](https://i-blog.csdnimg.cn/blog_migrate/b942459b6e55c412dc1804fa7fa1f41a.jpeg)
在使两者的指数相同之后将两者相加会得到:
![d049992b45be432c73ea778ae6879013.png](https://i-blog.csdnimg.cn/blog_migrate/6c330c0197b16dfd4e938cfb25ccc523.jpeg)
当以浮点表示时,它将变为:
![f19186034609410021ede2909c5af28d.png](https://i-blog.csdnimg.cn/blog_migrate/62d6a15585af739484c28efd19b65416.jpeg)
这就是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 场精选专题技术和行业论坛,超强干货+技术剖析+行业实践立体解读,深入解析热门技术在行业中的实践落地。
![9e5be1df8971291df1cf2d6eaa34bc77.png](https://i-blog.csdnimg.cn/blog_migrate/f54d104436f030cfee2cddb31eeed07e.jpeg)