在 Python 中舍入以避免机器精度错误
Rounding in Python to avoid machine precision errors
我想检查一个浮点数是否是另一个浮点数的倍数,但 运行 遇到机器精度问题。例如:
t1 = 0.02
factor = 0.01
print(t1%factor==0)
以上输出True
,但是
t2 = 0.030000000000000002
print(round(t2,5)%factor==0)
这输出 False
。在我的代码中的某些点,我正在检查的数字会产生这些机器精度错误,我认为我可以简单地通过四舍五入来解决这个问题(我的代码后面需要 5 位小数,但如果我只需四舍五入到小数点后两位)。
为什么上面的检查 round(t2,5)%factor==0
没有按预期工作?我该如何解决?
一般来说,Python 中的浮点数是...乱七八糟的,找不到更好的词了。他们可以以非常出乎意料的方式行事。 (您可以阅读有关该行为的更多信息 here。)
然而,为了您的目标,更好的方法是:
t2 = 0.03000003
factor = 0.01
precision = 10000 # 4 digits
print(int(t2*precision)%int(factor*precision)==0)
将数学转移到基于整数的计算可以解决大部分问题。
它没有按预期工作,因为检查浮点数是否相等几乎从不按预期工作。快速修复是使用 math.isclose
。这也允许您调整您的容忍度。记住在做算术mod r的时候,r等于0,所以你应该检查你是否接近于0或r。
import math
t1 = 0.02
factor = 0.01
res = t1 % factor
print(math.isclose(res, 0) or math.isclose(res, factor))
这是非常快速和肮脏的,您需要确保您的公差对这两项检查都正确且等效。
您应该使用十进制模块。 decimal 模块提供对快速正确舍入的十进制浮点运算的支持。
import decimal
print( decimal.Decimal('0.03') % decimal.Decimal('0.01') == decimal.Decimal('0') )
给出:
True
我想检查一个浮点数是否是另一个浮点数的倍数,但 运行 遇到机器精度问题。例如:
t1 = 0.02
factor = 0.01
print(t1%factor==0)
以上输出True
,但是
t2 = 0.030000000000000002
print(round(t2,5)%factor==0)
这输出 False
。在我的代码中的某些点,我正在检查的数字会产生这些机器精度错误,我认为我可以简单地通过四舍五入来解决这个问题(我的代码后面需要 5 位小数,但如果我只需四舍五入到小数点后两位)。
为什么上面的检查 round(t2,5)%factor==0
没有按预期工作?我该如何解决?
一般来说,Python 中的浮点数是...乱七八糟的,找不到更好的词了。他们可以以非常出乎意料的方式行事。 (您可以阅读有关该行为的更多信息 here。)
然而,为了您的目标,更好的方法是:
t2 = 0.03000003
factor = 0.01
precision = 10000 # 4 digits
print(int(t2*precision)%int(factor*precision)==0)
将数学转移到基于整数的计算可以解决大部分问题。
它没有按预期工作,因为检查浮点数是否相等几乎从不按预期工作。快速修复是使用 math.isclose
。这也允许您调整您的容忍度。记住在做算术mod r的时候,r等于0,所以你应该检查你是否接近于0或r。
import math
t1 = 0.02
factor = 0.01
res = t1 % factor
print(math.isclose(res, 0) or math.isclose(res, factor))
这是非常快速和肮脏的,您需要确保您的公差对这两项检查都正确且等效。
您应该使用十进制模块。 decimal 模块提供对快速正确舍入的十进制浮点运算的支持。
import decimal
print( decimal.Decimal('0.03') % decimal.Decimal('0.01') == decimal.Decimal('0') )
给出:
True