python - 如何打印浮点数的全精度 [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 在这个特定用例中。
解决方案
更新:在 Python 3str
中,浮点数保证产生具有全精度的字符串文字
在 Python 2 中不是这种情况。例如str(1.0000000000000002)
在'1.0'
Python 2 中,但在 Python 3 中它'1.0000000000000002'
按预期提供。
这通常是混淆的根源,因为print(x)
可能没有x
完全精确地打印,得出错误的结论 - 就像在问题的例子中一样。
有关此更改的背景,请参见此处。
Python 2 解决方案
获得具有完整精度的浮点数的字符串表示的一个简单解决方案是使用repr
or 或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 浮点数具有无损往返,因此可以保证它产生的位数是足够的。
推荐阅读
- sql - 密集排名,按 A 列分区,按 B 列更改递增,但按 C 列排序
- php - PHP 如何正确创建 url?
- c# - 如何从 C# 中的接收 CoAP 包中获取 IP 地址?
- c++ - 为什么“(!v.empty())”比“(v.size()> 0)”更好?
- php - (内部)加入此表时导致此内存泄漏的原因是什么?
- regex - 正则表达式向后读取到文件路径中的句号
- clojure - 替代在 Clojure 中使用 REPL 来快速尝试东西
- android - 从 FirebaseMessagingService 调用 Activity 方法
- android - Android LiveData,ViewModel,无法添加具有不同生命周期的相同观察者
- python - Neptune InternalFailureException:无法从主机顶点获取可附加