Python 为什么打印(0.3)打印0.3而不是0.300000000004

Python 为什么打印(0.3)打印0.3而不是0.300000000004,python,python-3.x,Python,Python 3.x,所以我想我基本上理解了浮点运算的工作原理,以及为什么我们不能对某些运算得到“精确”的结果 我被@MikeMüller的建议搞糊涂了 我的理解如下。 如果我们写小数位,它会是这样的: 1000 100 10 1。1/10 1/100 1/1000 它在二进制文件中看起来是这样的: 8421。1/2 1/4 1/8 因此,我们将0.5、0.25或0.125精确地存储在内存中,而不是例如0.3 那么为什么python会输出以下内容: print(0.1) print(0.2) print(0.3)

所以我想我基本上理解了浮点运算的工作原理,以及为什么我们不能对某些运算得到“精确”的结果

我被@MikeMüller的建议搞糊涂了


我的理解如下。 如果我们写小数位,它会是这样的:
1000 100 10 1。1/10 1/100 1/1000

它在二进制文件中看起来是这样的:
8421。1/2 1/4 1/8

因此,我们将0.5、0.25或0.125精确地存储在内存中,而不是例如0.3

那么为什么python会输出以下内容:

print(0.1)
print(0.2)
print(0.3)
print(0.1 + 0.2)

>>>0.1
>>>0.2
>>>0.3
>>>0.30000000000000004
我认为它应该输出

>>>0.1
>>>0.2
>>>0.30000000000000004
>>>0.30000000000000004
我错在哪里


我的问题不是重复的
因为OP不明白为什么0.1+0.2!=0.3. 这不是我问题的主题

因为它们不一样,因为
0.1
0.2
尚未正确表示。因此:

>>>print("%.20f" % (0.1+0.2))
0.30000000000000004441

>>>print("%.20f" % 0.3)
0.29999999999999998890

>>>print(0.29999999999999998890)
0.3
因此,打印内容完全取决于Python规则,特别是考虑到纯
0.3
表示比
0.1+0.2
更接近实际的
0.3

以下是相关摘录:

有趣的是,有许多不同的十进制数字共享 相同的近似二进制分数。例如,数字
0.1
0.100000000000001
0.1000000000000005555115123125782702118158340451015625
都近似为
3602879701896397/2**55
。因为所有这些都是十进制的 值共享相同的近似值,其中任何一个都可以是 显示时仍保留不变的
eval(repr(x))==x

历史上,Python提示符和内置的
repr()
函数 选择具有17个有效数字的一个,
0.100000000000001
。 从Python3.1开始,Python(在大多数系统上)现在能够 选择其中最短的,只需显示
0.1


为了使舍入问题不那么明显,通常浮点数字在打印时没有最后一位数字,而最后一位数字是舍入的。这恰恰是为了隐藏您希望看到的问题

因此,0.300000000000000004将四舍五入为0.3

但是,如果您有意进行这样的计算以避免这种舍入,那么您可以很容易地重现问题。例如,将结果乘以1e+6。你会看到你所看到的

有趣的是,有许多不同的十进制数共享相同的近似二进制分数。例如,数字0.1和0.100000000000001以及0.10000000000000555115123125782702118158340451015625都近似为3602879701896397/2**55。由于所有这些十进制值共享相同的近似值,因此可以显示其中任何一个,同时仍保留不变的eval(repr(x))==x

从历史上看,Python提示符和内置repr()函数会选择具有17个有效数字的一个,即0.100000000000001。从Python3.1开始,Python(在大多数系统上)现在可以选择其中最短的一个,并且只显示0.1


这就是为什么它可以显示
0.3
,因为这是存储为二进制表示的最短字符串。
0.1+0.2
稍高的结果不能显示为短于
0.300000000004

的字符串,这是为什么?1/10和2/10不能精确地表示为二元分数。今天(2010年7月)几乎所有的机器都使用IEEE-754浮点算法,几乎所有的平台都将Python浮点映射到IEEE-754“双精度”。754双精度包含53位精度,因此在输入时,计算机努力将0.1转换为最接近的分数,其形式为J/2**N,其中J是一个正好包含53位的整数。重写它们不是重复的,关闭这是一个错误@彼得:谢谢你,我也这么认为……就像我发现了同样的东西一样——堆积如山,永不停歇的比赛!谢谢你,我想到过这样的事。伟大的安瑟。