浮点数取模问题
我遇到了一个非常奇怪的bug。你可以看看代码里的注释,了解这个bug到底是什么。简单来说,一个变量对1取模时返回了1(但它实际上并不等于1!)。我猜这可能是显示的问题,浮点数非常接近1,但并不完全等于1。不过,它应该对1取模后结果是0。我很难测试这个情况,因为(last % 1)并不等于1.0!当我把相同的数字放到另一个Python终端时,一切都正常。到底发生了什么呢?
def r(k,i,p):
first = i*p
last = first + p
steps = int((i+1)*p) - int(i*p)
if steps < 1:
return p
elif steps >= 1:
if k == 0:
return 1 - (first % 1)
elif k == steps:
if i == 189:
print last, 1, type(last), last % 1, last - int(last)
# Prints: 73.0 1 <type 'float'> 1.0 1.0
print last % 1 == 1 # Returns False
if last % 1 == 1.0:
return 0
return (last % 1)
else:
return 1
5 个回答
3
你应该使用 math.fmod(x, y)。这里有一段来自 http://docs.python.org/library/math.html 的摘录:
“注意,Python 中的表达式 x % y 可能不会返回相同的结果。C 语言标准的意图是 fmod(x, y) 的结果应该严格(数学上;精确到无限)等于 x - n*y,其中 n 是某个整数,结果的符号和 x 一样,且绝对值小于 y 的绝对值。而 Python 的 x % y 返回的结果则是 y 的符号,并且对于浮点数参数可能无法精确计算。例如,fmod(-1e-100, 1e100) 的结果是 -1e-100,但 Python 的 -1e-100 % 1e100 的结果是 1e100-1e-100,这个值无法精确表示为浮点数,结果会意外地四舍五入到 1e100。因此,在处理浮点数时,通常推荐使用 fmod() 函数,而在处理整数时,则更倾向于使用 Python 的 x % y。”
6
打印出来的数字可能没有显示它的全部精度,也就是说,可能没有显示出它的真实样子。你可以用 repr()
这个方法来查看完整的数字。
>>> last=72.99999999999999
>>> print last, 1, type(last), last % 1, last - int(last)
73.0 1 <type 'float'> 1.0 1.0
>>> print last % 1 == 1
False
>>> print repr(last), 1, type(last), repr(last%1), repr(last - int(last))
72.999999999999986 1 <type 'float'> 0.99999999999998579 0.99999999999998579
>>>
6
欢迎来到IEEE754,祝你玩得愉快。