Floating point "g" format not stripping trailing zeros

Ian Kelly ian.g.kelly at gmail.com
Fri Feb 13 11:52:10 EST 2015


On Fri, Feb 13, 2015 at 2:26 AM, Hrvoje Nikšić <hniksic at gmail.com> wrote:
> Ian Kelly writes:
>> When you specify the a precision of 15 in your format string, you're
>> telling it to take the first 15 of those. It doesn't care that the
>> last couple of those are zeros, because as far as it's concerned,
>> those digits are significant.
>
> OK, it's a bit surprising, but also consistent with the rest of the
> decimal module. Thanks for clearing it up.
>
> My concrete use case is printing an arbitrary fraction as a
> user-readable decimal, rounded to the specified number of digits, and
> using the exponential notation where appropriate:
>
> import decimal
> _dec_fmt_context = decimal.Context(prec=15, rounding=decimal.ROUND_HALF_UP)
> def _format(frac):
>     with decimal.localcontext(_dec_fmt_context):
>         dec = decimal.Decimal(frac.numerator) /
> decimal.Decimal(frac.denominator)
>         return '{:g}'.format(dec)
>
> The decimal obtained by dividing the numerator with the denominator
> includes trailing zeros. Calling normalize() to get rid of them will
> have the unfortunate side effect of turning 9806650 into 9.80665e+6,
> and the method recommended in the documentation:
>
> def remove_exponent(d):
>     return d.quantize(decimal.Decimal(1)) if d == d.to_integral() else
> d.normalize()
>
> ...will raise "decimal.InvalidOperation: quantize result has too many
> digits for current context" when the number is too large.

In that case I think you just want to normalize instead. So:

>>> def remove_exponent(d):
...   if d == d.to_integral():
...     try:
...       return d.quantize(1)
...     except decimal.InvalidOperation:
...       pass
...   return d.normalize()
...
>>> remove_exponent(D('123000000'))
Decimal('123000000')
>>> remove_exponent(D('123.4567'))
Decimal('123.4567')
>>> remove_exponent(D('123.4567890'))
Decimal('123.456789')
>>> remove_exponent(D('123e6'))
Decimal('123000000')
>>> remove_exponent(D('1234567890123456789012345678901234567890'))
Decimal('1.234567890123456789012345679E+39')



More information about the Python-list mailing list