[大咖. 来了 第 7 期] 10 月 24 日晚 8 点观看《智能导购对话机器人实践》
打开你的 Python, 输入「0.1+0.2=」, 结果是多少? 0.30000000000000004 对不对? 为什么结果不是 0.3? 本文作者给出了详细的解释.
从小我们就知道 0.1 + 0.2=0.3. 但是, 在光怪陆离的计算世界中, 运算方式却大相径庭.
我最近开始用 JavaScript 进行编码, 在阅读数据类型时, 我注意到 0.1 + 0.2 不等于 0.3 的奇怪行为. 我向 Stack Overflow 寻求帮助, 在上面找到了一些有用的帖子. 如下图所示:
Stack Overflow 界面图像.
经过大量的研究和数学运算后, 我得出结论, 这不是错误. 这是数学运算中的浮点运算. 让我们进一步了解内在机制.
问题描述: 为什么 0.1 + 0.2 = 0.30000000000000004?
如果你用 Java 或 C 语言编过程, 那你一定知道用于存储值的不同数据类型. 我们在前面的讨论中将考虑两种数据类型: 整数型和浮点型.
整数型存储整数, 而浮点型存储小数.
在这之前, 我们先来了解一个小概念: 为了实现计算, 数字是如何表示的? 极小数和极大数通常用科学计数法表示, 即:
同样, 如果一个用科学计数法书写的数字小数点前有一个非零的十进制数, 则该数字是标准化写法. 例如, 0.0005606 用科学计数法的标准化写法为:
Significant 是指不包含零的有效数字, base 表示所使用的进制 -- 此处为十进制 (10).Exponent(指数) 表示小数点需要向左或向右移动的步数.
现在, 有两种显示浮点数的方法: 单精度和双精度. 在进行浮点运算时, 单精度使用 32 位, 而双精度使用 64 位.
与许多其他编程语言不同, JavaScript 并未定义不同类型的数字数据类型, 而是始终遵循国际 IEEE 754 标准, 将数字存储为双精度浮点数.
这种格式以 64 位存储数字, 其中数字 (分数) 存储在位 0 到 51 中, 指数存储在位 52 到 62 中, 符号存储在位 63 中.
IEEE754 双精度标准.
我们按 IEEE754 标准用 64 位表示 0.1. 第一步是将十进制的 0.1 转换为二进制的 0.1. 首先将 0.1 乘以 2, 然后将小数点前的数字分离出来, 得到其相应的二进制数.
重复此操作至 64 位. 然后把它们按升序排列, 获取尾数, 再根据双精度标准, 我们将把其四舍五入到 52 位.
尾数
用科学计数法表示二进制 0.1 并只保留前 52 位:
尾数部分处理好后. 现在我们用下面的方式处理指数:
这里, 11 代表我们要使用的 64 位表示的指数位数,-4 代表科学计数中的指数.
所以最终数字 0.1 的表示形式是:
同理, 0.2 表示为:
将两个数相加, 得到:
转换为浮点数, 它变成:
这就是 0.1 + 0.2 = 0.30000000000000004 的原因.
来源: http://news.51cto.com/art/201910/604608.htm