问题描述
我知道0.1
实际上是0.0001100110011001100110011001100110011001100110011...
。
但是,例如,在Python中,当我们添加0.1和0.2时为什么向提示符输出0.30000000000000004
?
为什么不只是保持幻想,给使用者蓝色药丸并告诉他0.1 + 0.2为0.3?无知是幸福,不是吗?
解决方法
Python规范对浮点行为并不严格,但是许多实现使用IEEE-754 binary64格式。用这种格式表示的数字中,最接近.1的数字是:
.000110011001100110011001100110011001100110011001100110102,
最接近.2的是:
.001100110011001100110011001100110011001100110011001101002.
这些的实数总和是:
.010011001100110011001100110011001100110011001100110011102.
该数字有54位有效数字。 (显示了56位数字,用于对齐和与之前的数字进行比较。前导0仅用于对齐,而尾随0对值无意义,因此从前1个到后1个有54位数字。)格式的有效位数(表示的小数部分)只有53位。因此,该数字不能以binary64格式表示。
它恰好在两个可表示数字之间:
.010011001100110011001100110011001100110011001100110011002 and .010011001100110011001100110011001100110011001100110100002.
有平局时,打破平局的常见规则是使用偶数位在低位的数字。由于第一个以0111结束的位数适合有效位数,第二个以1000结束,因此选择了第二个,这是使用浮点加法将这两个数字相加的结果。
该值为0.3000000000000000444089209850062616169452667236328125。
请记住,进行加法的计算机或软件部分不知道这些数字最初来自.1或2.。它仅具有上面显示的位。它得到的和介于两个可表示的值之间,并且必须选择一个作为结果。该选择的规则是使用低位数的值。
一旦获得结果,就可以选择格式化的方式。同样,Python规范并不严格,但是一种格式化行为是仅显示足够的数字以唯一地将数字与相邻的可表示值区分开。最接近的.3可表示数字是0.299999999999999988897769753748434595763683319091796875,因此,在显示该数字时,将显示“ .3”。在显示0.3000000000000000444089209850062616169452667236328125时,我们无法使用“ .3”,因为这无法将其与0.299999999999999988897769753748434595763683319091796875区分。因此,为了区分它,它必须显示为“ 0.30000000000000004”。
另一种常见的格式化方法是使用固定数量的十进制数字(例如17)将数字转换为十进制,然后删除尾随的零。在这种情况下,结果将是相同的:“。3”代表0.2999999999999999999988897769753748434595763683319091796875,“ 0.30000000000000004”代表0.3000000000000000444089209850062616169452667236328125。
此外,向程序员隐藏信息不是一个好主意。这样做会使错误的想法发展壮大并导致错误的发生。当价值观并非天真的解释可能认为的那样时,最好表现出差异而不是隐瞒它们。