首页 > 解决方案 > 如何打印浮点数的全精度 [Python]

问题描述

我编写了以下函数,其中传递了 x,y 的值:

def check(x, y):
    print(type(x))
    print(type(y))
    print(x)
    print(y)
    if x == y:
        print "Yes"

现在,当我打电话给 它时check(1.00000000000000001, 1.0000000000000002) ,它正在打印:

<type 'float'>
<type 'float'>
1.0
1.0

现在从变量 x 和 y 的打印语句中,我很难调试为什么 x != y (尽管两者都打印相同的值)。虽然我通过打印 x - y 解决了它,这给了我不同之处,但是有没有办法修改打印语句,以便在不使用任何外部打印库和减法解决方案的情况下知道为什么 x!=y 在这个特定用例中。

标签: pythonpython-2.7floating-point

解决方案


更新:在 Python 3str中,浮点数保证产生具有全精度的字符串文字

在 Python 2 中不是这种情况。例如str(1.0000000000000002)'1.0'Python 2 中,但在 Python 3 中它'1.0000000000000002'按预期提供。

这通常是混淆的根源,因为print(x)可能没有x完全精确地打印,得出错误的结论 - 就像在问题的例子中一样。

有关此更改的背景,请参见此处


Python 2 解决方案

获得具有完整精度的浮点数的字符串表示的一个简单解决方案是使用repror 或json.dumps.

JSON 序列化/反序列化必须确保往返是无损的,因此,实现会生成您正在寻找的字符串表示:

def check(x, y):
    print(repr(x))
    print(repr(y))
    print("x == y is {}".format(x == y))
In [1]: check(1.00000000000000001, 1.0000000000000002)
1.0
1.0000000000000002
x == y is False

In [2]: check(1e-300, 2e-300)
1e-300
2e-300
x == y is False

In [3]: check(1e+300, 2e+300)
1e+300
2e+300
x == y is False

这也说明1.00000000000000001实际上1.0。这也可以通过使用 枚举 1.0 附近的数字来检查np.nextafter,这会产生下一个更大/更小的可表示浮点值:

    0.9999999999999994
    0.9999999999999996
    0.9999999999999997
    0.9999999999999998
    0.9999999999999999
[*] 1.0               
    1.0000000000000002
    1.0000000000000004
    1.0000000000000007
    1.0000000000000009
    1.000000000000001 

回复@罗伯特:

json.dumps也适用于您的情况。格式化'.60g'只是产生一个文字,它具有比 IEEE 双精度数字可以容纳的更多不必要的数字。由 产生的其他文字的精度json.dumps足以表示该特定浮点数,您可以通过以下方式检查:

在此处输入图像描述

最接近的两个 IEEE 文字1./math.sqrt(3.)是:

在此处输入图像描述

第一个已经是最接近的可能表示形式,存储更多的数字1./math.sqrt(3.)将始终为您返回相同的数字。

json.dumps对 64 位 IEEE 浮点数具有无损往返,因此可以保证它产生的位数是足够的。


推荐阅读