Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting Ceil() of Decimal in python?

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

like image 689
Gunjan Avatar asked May 08 '10 22:05

Gunjan


2 Answers

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.

like image 120
Mark Dickinson Avatar answered Sep 25 '22 14:09

Mark Dickinson


x = decimal.Decimal('8.00000000000000000000001')
with decimal.localcontext() as ctx:
    ctx.prec=100000000000000000
    ctx.rounding=decimal.ROUND_CEILING
    y = x.to_integral_exact()
like image 44
Robert Clark Avatar answered Sep 22 '22 14:09

Robert Clark