drop trailing zeros from decimal

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')

Answer is mentioned in FAQ (https://docs.python.org/2/library/decimal.html#decimal-faq) but does not explain things.

To drop trailing zeros for fraction part you should use normalize:

>>> Decimal('100.2000').normalize()
Decimal('100.2')
>> Decimal('0.2000').normalize()
Decimal('0.2')

But this works different for numbers with leading zeros in sharp part:

>>> Decimal('100.0000').normalize()
Decimal('1E+2')

In this case we should use `to_integral':

>>> Decimal('100.000').to_integral()
Decimal('100')

So we could check if there's a fraction part:

>>> Decimal('100.2000') == Decimal('100.2000').to_integral()
False
>>> Decimal('100.0000') == Decimal('100.0000').to_integral()
True

And use appropriate method then:

def remove_exponent(num):
    return num.to_integral() if num == num.to_integral() else num.normalize()

Try it:

>>> remove_exponent(Decimal('100.2000'))
Decimal('100.2')
>>> remove_exponent(Decimal('100.0000'))
Decimal('100')
>>> remove_exponent(Decimal('0.2000'))
Decimal('0.2')

Now we're done.


There's probably a better way of doing this, but you could use .rstrip('0').rstrip('.') to achieve the result that you want.

Using your numbers as an example:

>>> s = str(Decimal('2.5') * 10)
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
25
>>> s = str(Decimal('2.5678') * 1000)
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
2567.8

And here's the fix for the problem that gerrit pointed out in the comments:

>>> s = str(Decimal('1500'))
>>> print s.rstrip('0').rstrip('.') if '.' in s else s
1500

Answer from the Decimal FAQ in the documentation:

>>> def remove_exponent(d):
...     return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()

>>> remove_exponent(Decimal('5.00'))
Decimal('5')

>>> remove_exponent(Decimal('5.500'))
Decimal('5.5')

>>> remove_exponent(Decimal('5E+3'))
Decimal('5000')

Tags:

Python

Decimal