drop trailing zeros from decimal

b10hazard picture b10hazard · Jun 27, 2012 · Viewed 50.6k times · Source

I have a long list of Decimals and that I have to adjust by factors of 10, 100, 1000,..... 1000000 depending on certain conditions. When I multiply them there is sometimes a useless trailing zero (though not always) that I want to get rid of. For example...

from decimal import Decimal

# outputs 25.0,  PROBLEM!  I would like it to output 25
print Decimal('2.5') * 10

# outputs 2567.8000, PROBLEM!  I would like it to output 2567.8
print Decimal('2.5678') * 1000

Is there a function that tells the decimal object to drop these insignificant zeros? The only way I can think of doing this is to convert to a string and replace them using regular expressions.

Should probably mention that I am using python 2.6.5

EDIT senderle's fine answer made me realize that I occasionally get a number like 250.0 which when normalized produces 2.5E+2. I guess in these cases I could try to sort them out and convert to a int

Answer

senderle picture senderle · Jun 27, 2012

You can use the normalize method to remove extra precision.

>>> print decimal.Decimal('5.500')
5.500
>>> print decimal.Decimal('5.500').normalize()
5.5

To avoid stripping zeros to the left of the decimal point, you could do this:

def normalize_fraction(d):
    normalized = d.normalize()
    sign, digits, exponent = normalized.as_tuple()
    if exponent > 0:
        return decimal.Decimal((sign, digits + (0,) * exponent, 0))
    else:
        return normalized

Or more compactly, using quantize as suggested by user7116:

def normalize_fraction(d):
    normalized = d.normalize()
    sign, digit, exponent = normalized.as_tuple()
    return normalized if exponent <= 0 else normalized.quantize(1)

You could also use to_integral() as shown here but I think using as_tuple this way is more self-documenting.

I tested these both against a few cases; please leave a comment if you find something that doesn't work.

>>> normalize_fraction(decimal.Decimal('55.5'))
Decimal('55.5')
>>> normalize_fraction(decimal.Decimal('55.500'))
Decimal('55.5')
>>> normalize_fraction(decimal.Decimal('55500'))
Decimal('55500')
>>> normalize_fraction(decimal.Decimal('555E2'))
Decimal('55500')