pythonpython-3.xstringdecimalscientific-notation

Python decimal.Decimal producing result in scientific notation


I'm dividing a very long into much smaller number. Both are of type decimal.Decimal().

The result is coming out in scientific notation. How do I stop this? I need to print the number in full.

>>> decimal.getcontext().prec
50
>>> val
Decimal('1000000000000000000000000')
>>> units
Decimal('1500000000')
>>> units / val
Decimal('1.5E-15')

Solution

  • Render the decimal into a formatted string with a float type-indicator {:,f}, and it will display just the right number of digits to express the whole number, regardless of whether it is a very large integer or a very large decimal.

    >>> val
    Decimal('1000000000000000000000000')
    
    >>> units
    Decimal('1500000000')
    
    >>> "{:,f}".format(units / val)
    '0.0000000000000015'
    
    # very large decimal integer, formatted as float-type string, appears without any decimal places at all when it has none! Nice!
    
    >>> "{:,f}".format(units * val)
     '1,500,000,000,000,000,000,000,000,000,000,000'
    

    You don't need to specify the decimal places. It will display only as many as required to express the number, omitting that trail of useless zeros that appear after the final decimal digit when the decimal is shorter than a fixed format width. And you don't get any decimal places if the number has no fraction part.

    Very large numbers are therefore accommodated without having to second guess how large they will be. And you don't have to second guess whether they will be have decimal places either.

    Any specified thousands separator {:,f} will likewise only have effect if it turns out that the number is a large integer instead of a long decimal.

    Proviso

    Decimal(), however, has this idea of significant places, by which it will add trailing zeros if it thinks you want them.

    The idea is that it intelligently handles situations where you might be dealing with currency digits such as £ 10.15. To use the example from the documentation:

    >>> decimal.Decimal('1.30') +  decimal.Decimal('1.20')
    Decimal('2.50')
    

    It makes no difference if you format the Decimal() - you still get the trailing zero if the Decimal() deems it to be significant:

    >>> "{:,f}".format( decimal.Decimal('1.30') +  decimal.Decimal('1.20'))
    '2.50'
    

    The same thing happens (perhaps for some good reason?) when you treat thousands and fractions together:

    >>> decimal.Decimal(2500) * decimal.Decimal('0.001')
    Decimal('2.500')
    

    Remove significant trailing zeros with the Decimal().normalize() method:

    >>> (2500 * decimal.Decimal('0.001')).normalize()
    Decimal('2.5')