Получить Ceil() Десятичного в питоне?

Есть ли способ получить значение высокой точности десятичного числа в Python?

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

математика округляет значение и возвращает не точное значение

6 ответов

Решение
x = decimal.Decimal('8.00000000000000000000001')
with decimal.localcontext() as ctx:
    ctx.prec=100000000000000000
    ctx.rounding=decimal.ROUND_CEILING
    y = x.to_integral_exact()

Самый прямой способ взять потолок десятичного экземпляра x это использовать x.to_integral_exact(rounding=ROUND_CEILING), Там нет необходимости возиться с контекстом здесь. Обратите внимание, что это устанавливает Inexact а также Rounded флаги, где это уместно; если вы не хотите, чтобы флаги касались, используйте 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')

В отличие от большинства десятичных методов, to_integral_exact а также to_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.ceil перегружается для пользовательских типов в Python 3. В Python 2 math.ceil просто преобразует Decimal экземпляр для float Во-первых, это может привести к потере информации в процессе, что может привести к неверным результатам.

Вы можете сделать это, используя опцию точности и режима округления конструктора Context.

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

РЕДАКТИРОВАТЬ: Вы должны рассмотреть вопрос об изменении принятого ответа.. Хотя prec может быть увеличено по мере необходимости, to_integral_exact это более простое решение.

def decimal_ceil(x):
    int_x = int(x)
    if x - int_x == 0:
        return int_x
    return int_x + 1
>>> decimal.Context(rounding=decimal.ROUND_CEILING).quantize(
...   decimal.Decimal(800000000000000000001)/100000000000000000000, 0)
Decimal('9')

Просто используйте потенцию, чтобы сделать это. импорт математики

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
Другие вопросы по тегам