ceil() 函数未返回预期值
我正在使用ceil()函数来把浮点计算的结果向上舍入到最近的整数。遇到了各种不同的输入...
int(ceil(A*B))
这里有一些例子来说明这个问题:
int(ceil(1.01*100)) = 101
int(ceil(1.02*100)) = 102
int(ceil(1.03*100)) = 103
int(ceil(1.04*100)) = 104
int(ceil(1.05*100)) = 105
int(ceil(1.06*100)) = 106
int(ceil(1.07*100)) = 107
int(ceil(1.08*100)) = 108
int(ceil(1.09*100)) = 110 ***
int(ceil(1.10*100)) = 111 ***
int(ceil(1.11*100)) = 112 ***
int(ceil(1.12*100)) = 113 ***
int(ceil(1.13*100)) = 113
我意识到这和进行的浮点计算有关...
1.09*100 = 109.000000.... > 109
我完全不知道怎么可靠地捕捉到这个错误
虽然我有几个“粗糙”的方法,比如下面提到的那个,但我觉得这并不是一个足够稳健的解决方案
int(ceil((1.09*100)-0.00000001)) = 109
2 个回答
2
你说得对,这个问题是因为浮点数的精度有限。
decimal
模块可以帮助你解决这个问题:
from decimal import Decimal
from math import ceil
print int(ceil(Decimal("1.10") * 100))
需要注意的是,你必须把数字作为字符串提供给它,否则Python会先把它当作浮点数处理(这就是我们想要避免的精度问题)。
3
你的问题其实并不是新出现的,也不是Python特有的,而是浮点数计算本身就有的特点。所有曾经使用Fortran 4的老程序员都知道这一点:作为程序员,你需要了解你计算的预期精度ε。所以:
- 如果两个数字x和y的差的绝对值小于ε,也就是
| x - y | < ε
,那么可以认为它们是相等的。 - 小于x的最大整数是
floor(x + ε)
。 - 大于x的最小整数是
ceil(x - ε)
。
所以你提出的解决方案是正确的,只要你能知道ε的合适值。如果你在写一个模块,应该让用户能够指定这个值。