首页 > 解决方案 > 0.1 是一个近似值,但是当我们添加 0.1 和 0.2 时,为什么不在幕后进行四舍五入呢?

问题描述

我明白0.10.0001100110011001100110011001100110011001100110011...

但是,例如在 Python 中,为什么0.30000000000000004我们添加 0.1 和 0.2 时会输出到提示符?

为什么不继续幻想,给用户蓝色药丸并告诉他 0.1+0.2 是 0.3?无知是幸福的,不是吗?

标签: floating-pointusability

解决方案


Python 规范对浮点行为并不严格,但许多实现使用 IEEE-754 binary64 格式。在此格式可表示的数字中,最接近 0.1 的数字是:

.00011001100110011001100110011001100110011001100110011010 2 ,

最接近 0.2 的是:

.00110011001100110011001100110011001100110011001100110100 2 .

这些的实数和是:

.01001100110011001100110011001100110011001100110011001110 2 .

该数字有 54 位有效数字。(显示 56 位,用于对齐和与前面的数字比较。前导 0 仅用于对齐,尾随 0 对值没有意义,因此从第一个 1 到最后一个 1 有 54 位。) binary64格式只有 53 位有效数字(表示的小数部分)。所以这个数字不能用 binary64 格式表示。

它正好在两个可表示的数字之间:

.01001100110011001100110011001100110011001100110011001100 2和
.01001100110011001100110011001100110011001100110011010000 2 .

当出现平局时,打破平局的一般规则是使用低位偶数的数字。由于第一个在适合有效数字的位中以 0111 结尾,第二个以 1000 结尾,因此选择了第二个,这是使用浮点加法将这两个数字相加的结果。

该值为 0.3000000000000000444089209850062616169452667236328125。

请记住,进行加法运算的计算机或软件部分并不知道这些数字最初来自 0.1 或 0.2。它只有上面显示的位可以使用。它得到一个介于两个可表示值之间的总和,并且必须选择一个作为结果。该选择的规则是使用具有偶数低位的值。

一旦获得该结果,就可以选择如何格式化它。同样,Python 规范并不严格,但一种格式化行为是仅显示足够的数字以唯一地将数字与相邻的可表示值区分开来。最接近 0.3 的可表示数字是 0.299999999999999988897769753748434595763683319091796875,因此,当显示该数字时,将显示“.3”。当显示 0.3000000000000000444089209850062616169452667236328125 时,我们不能使用“.3”,因为它无法与 0.2999999999999999888977697537484345957636831909176 区分开来。因此,要区分它,必须显示为“0.30000000000000004”。

另一种常见的格式化方法是使用固定数量的十进制数字(例如 17)将数字转换为十进制,然后删除尾随零。在这种情况下,这将产生相同的结果,“ .3”对于0.29999999999999999999999999777697753748484845957633319091796875,以及“ 0.300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000444444444444444444444444444444444444444444444444444444444444444444444444444444444444000000000000000000000000000000000000000000000000000009090909090909.ANT”年份

此外,对程序员隐藏信息也不是一个好主意。这样做会使错误的想法滋生,并出现错误。当价值观与天真的解释所认为的不完全一样时,最好显示差异而不是隐藏它们。


推荐阅读