13

有没有办法在 python 中获得高精度 Decimal 的 ceil?

>>> import decimal;
>>> decimal.Decimal(800000000000000000001)/100000000000000000000
Decimal('8.00000000000000000001')
>>> math.ceil(decimal.Decimal(800000000000000000001)/100000000000000000000)
8.0

数学四舍五入并返回非精确值

4

6 回答 6

30

获取 Decimal 实例上限的最直接方法x是使用x.to_integral_exact(rounding=ROUND_CEILING). 这里没有必要搞乱上下文。请注意,这会在适当的情况下设置InexactRounded标志;如果您不想触摸标志,请x.to_integral_value(rounding=ROUND_CEILING)改用。例子:

>>> from decimal import Decimal, ROUND_CEILING
>>> x = Decimal('-123.456')
>>> x.to_integral_exact(rounding=ROUND_CEILING)
Decimal('-123')

与大多数 Decimal 方法不同,to_integral_exactandto_integral_value方法不受当前上下文精度的影响,因此您不必担心更改精度:

>>> from decimal import getcontext
>>> getcontext().prec = 2
>>> x.to_integral_exact(rounding=ROUND_CEILING)
Decimal('-123')

顺便说一句,在 Python 3.x 中,math.ceil它完全按照您的意愿工作,只是它返回的是一个int而不是一个Decimal实例。之所以可行,是因为math.ceilPython 3 中的自定义类型可重载。在 Python 2 中,math.ceil只需将Decimal实例转换为float第一个实例,在此过程中可能会丢失信息,因此您最终可能会得到不正确的结果。

于 2010-05-09T09:58:07.413 回答
6
x = decimal.Decimal('8.00000000000000000000001')
with decimal.localcontext() as ctx:
    ctx.prec=100000000000000000
    ctx.rounding=decimal.ROUND_CEILING
    y = x.to_integral_exact()
于 2010-05-08T23:14:25.643 回答
4

您可以使用 Context 构造函数的精度和舍入模式选项来执行此操作。

ctx = decimal.Context(prec=1, rounding=decimal.ROUND_CEILING)
ctx.divide(decimal.Decimal(800000000000000000001), decimal.Decimal(100000000000000000000))

编辑:您应该考虑更改接受的答案。虽然prec可以根据需要增加,但这to_integral_exact是一个更简单的解决方案。

于 2010-05-08T22:56:43.760 回答
0
>>> decimal.Context(rounding=decimal.ROUND_CEILING).quantize(
...   decimal.Decimal(800000000000000000001)/100000000000000000000, 0)
Decimal('9')
于 2010-05-08T22:59:41.420 回答
0
def decimal_ceil(x):
    int_x = int(x)
    if x - int_x == 0:
        return int_x
    return int_x + 1
于 2010-05-08T23:00:25.460 回答
0

只需使用效力即可。导入数学

def lo_ceil(num, potency=0): # Use 0 for multiples of 1, 1 for multiples of 10, 2 for 100 ...
      n = num / (10.0 ** potency)
      c = math.ceil(n)
      return c * (10.0 ** potency)

lo_ceil(8.0000001, 1) # return 10
于 2013-01-22T22:07:06.307 回答