高精度的ceil函数

2 投票
4 回答
2855 浏览
提问于 2025-04-20 23:26

我该怎么把一个数字向上取整到下一个整数,并且做到很精确呢?

Input: var1 = (8193/4096) # var1 = 2.00024414063
Output: 3 # As an integer

>>> var1 = 8193/4096
>>> import math
>>> math.ceil(var1)
2.0
>>> math.ceil(8193/4096)
2.0
>>> import numpy
>>> numpy.ceil(8193/4096)

我怎么才能优雅地完成这个操作呢?

4 个回答

1

还有一种纯整数的方法,对我来说比用双重否定的方式更直观,不过这种方法只适用于正数 y

def myceil(x, y):
    return (x + y - 1) // y
2
-(-8193/4096)

这个方法进行精确的整数除法,并且会向上取整。

所以它比使用浮点数要好得多。

原因很简单,因为 a/b 是向下取整的,所以 -a/b 也是向下取整负数,这样 -(-a/b) 就能给你想要的结果。

为了支持 Python 3(这总是个好主意),可以使用 -(-8193//4096)


这里有个简单的例子,说明它比 ceil 更好:

>>> -(-10**17 // 3)
33333333333333334
>>> int(ceil(10**17 / 3.0))
33333333333333332
2

问题: 你现在在做整数除法,这样会自动计算出商的下限值,并给你一个整数结果。

解决办法: 先把其中一个数(被除数或除数)转换成 float 类型:

math.ceil( float(8193)/4096 ) 
3.0

或者: 只需在其中一个数字后面加上 .0,这样就能把它变成浮点数,例如:

math.ceil( 8193.0/4096 )
3.0

或者: 从 __future__ 模块导入 division 功能,这样默认就可以使用 Python 3 的除法:

from __future__ import division
math.ceil( 8193.0/4096 )

Python 3: 不过在 Python 3 中,/ 是真正的除法,所以你不需要担心上面的问题。如果你想重现你遇到的情况,你需要使用 // 来进行整数除法。// 的功能在所有 Python 版本中都是一样的。

4

在Python 2中,这段代码:

>>> var1 = 8193/4096

其实并不是你想的那样。在Python 2里,两个整数相除总是会返回一个整数(也就是去掉小数部分的结果)。

>>> 8193/4096
2

...然后调用math.ceil()对2进行处理,结果还是2。

如果你把其中一个或两个值转换成浮点数(也就是带小数的数),那么它就会按照你想要的方式工作:

>>> v = 8193/4096.0
>>> v
2.000244140625
>>> math.ceil(v)
3.0

有几个替代方案:

a) 切换到Python 3,在那里除法的行为就像你想要的那样:

bgporter@zappa:~$ python3
Python 3.4.0 (default, Apr 11 2014, 13:05:18)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 8193/4096
2.000244140625
>>>

b) 在Python 2中启用Python 3的除法功能,方法如下:

bgporter@varese ~:python
Python 2.7.5 (default, Mar  9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import division
>>> 8193/4096
2.000244140625

撰写回答