2014-04-30 84 views
0

我正在使用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 

我不知道如何捕获这个bug可靠

虽然我有一对夫妇的“粗”的方法,如一个概述如下,我不认为这是一个足够强大的解决方案

int(ceil((1.09*100)-0.00000001)) = 109 
+5

根据数字来自哪里,您可能需要查看['Decimal'](https://docs.python.org/2/library/decimal.html)模块。只要输入'1.09'已经是'1.0900000000000001' – mhlester

回答

3

你的问题既不是新的,也不是python特定的,但它是浮点计算固有的。所有曾经使用Fortran 4的dynosaurus都知道它:you作为程序员必须知道预期的精度ε的计算。所以:

  • 两个数x和y是被视为等于如果| x - y | < ε
  • 的最大整数不如x是floor(x + ε)
  • 的最小整数大于x是ceil(x - ε)

所以您提出的解决方案是一个很好的解决方案,前提是您有一种方法可以知道什么是最好的价值。如果你正在编写一个模块,你应该允许用户指定它。

+0

好玩的技巧欢呼。目前它会很方便,只有浮点数字的表示可用。这让我想起了我对CAD应用程序的编程,因此必须始终精确地测试两点的重合。 –

+0

为了一个好的,简洁的解释而欢呼。 (巧合的是,这也将一些旧的Fortran转换为CAD应用程序) –

2

你是对的,这个问题在浮动的精度有限起源数。

decimal模块是你的朋友:

from decimal import Decimal 
from math import ceil 

print int(ceil(Decimal("1.10") * 100)) 

注意,那你真的要提供作为串号,否则它是第一个被Python解析为浮点数(在这里,我们用精度得到了问题,我们想避免)。

+0

我已经开始读取到十进制模块,指针 –