我使用python2数学模块用fsum计算总和。我知道0.1通常不能存储二进制。就我所知,math.fsum应该以某种方式解决这个问题。
import math
math.fsum([0.0, 0.1])
#0.1
math.fsum([0.1, 0.1])
#0.2
math.fsum([0.2, 0.1])
#0.30000000000000004
math.fsum([0.3, 0.1])
#0.4
math.fsum([0.4, 0.1])
#0.5
所以math.fsum([0.2,0.1])== 0.3将为False。这应该是这样的吗?我做错了吗?
我怎样才能得到0.2 + 0.1 == 0.3为真?
答案 0 :(得分:6)
你误解了math.fsum
的作用。它计算给定输入的最准确可能总和 (即,与输入的精确数学和最接近的可精确表示的值)。它并没有用你原先想到的数字神奇地取代它的输入。
在上面的第三行中,math.fsum
的输入是一个包含值0.1000000000000000055511151231257827021181583404541015625
和0.200000000000000011102230246251565404236316680908203125
的列表(请记住,使用二进制浮点数,所见即所得不是你获取;这里我显示了Python使用的确切值。这两个值的精确总和是0.3000000000000000166533453693773481063544750213623046875
,最接近的可表示的IEEE 754 binary64浮动到那个精确的总和是0.3000000000000000444089209850062616169452667236328125
,这正是你得到的。
您要求math.fsum
的行为就像给出了确切的值0.1
和0.2
一样,但它无法知道这些是什么你想要什么:它只能对你提供的输入进行操作。
请注意,在大多数机器上,添加两个浮点数已经正确舍入,因此使用math.fsum
没有任何优势。 math.fsum
旨在消除累加 more 所涉及的舍入错误的累积,而不是两个浮点数。
答案 1 :(得分:1)
实际上,你应该避免使用等于运算符的浮点数。因为计算机以二进制形式呈现它们,并且只是浮点数的近似值。
如果你真的需要检查两个浮点数是否相等,你需要定义一个容差:
例如:
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
请参考:
我发现这个有趣的网站:
What is the best way to compare floats for almost-equality in Python?
在大多数语言中,这0.1 + 0.2不等于0.3出口。