getting Ceil() of Decimal in python?

Gunjan picture Gunjan · May 9, 2010 · Viewed 11.4k times · Source

Is there a way to get the ceil of a high precision Decimal in python?

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

math rounds the value and returns non precise value

Answer

Mark Dickinson picture Mark Dickinson · May 9, 2010

The most direct way to take the ceiling of a Decimal instance x is to use x.to_integral_exact(rounding=ROUND_CEILING). There's no need to mess with the context here. Note that this sets the Inexact and Rounded flags where appropriate; if you don't want the flags touched, use x.to_integral_value(rounding=ROUND_CEILING) instead. Example:

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

Unlike most of the Decimal methods, the to_integral_exact and to_integral_value methods aren't affected by the precision of the current context, so you don't have to worry about changing precision:

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

By the way, in Python 3.x, math.ceil works exactly as you want it to, except that it returns an int rather than a Decimal instance. That works because math.ceil is overloadable for custom types in Python 3. In Python 2, math.ceil simply converts the Decimal instance to a float first, potentially losing information in the process, so you can end up with incorrect results.