194
votes

How can I display this:

Decimal('40800000000.00000000000000') as '4.08E+10'?

I've tried this:

>>> '%E' % Decimal('40800000000.00000000000000')
'4.080000E+10'

But it has those extra 0's.

12
kinda doubleposting, you could have used this topic you just started: stackoverflow.com/questions/6913166/… - Samuele Mattiuzzo
nah, not at all. I wanted to separate this into the easy question (how to do it in Python) and the hard, obscure question that I doubt anyone will answer (how to do it in Django). Notice how this already has an answer. I'm now halfway to my final answer instead of 0% if I had posted them together. Besides that, separating the questions makes it easier for people to search for the answers. E.,g if Bob is searching for a decimal formatting question he might skip a SO questin with Django in the title. - Greg

12 Answers

179
votes
from decimal import Decimal

'%.2E' % Decimal('40800000000.00000000000000')

# returns '4.08E+10'

In your '40800000000.00000000000000' there are many more significant zeros that have the same meaning as any other digit. That's why you have to tell explicitly where you want to stop.

If you want to remove all trailing zeros automatically, you can try:

def format_e(n):
    a = '%E' % n
    return a.split('E')[0].rstrip('0').rstrip('.') + 'E' + a.split('E')[1]

format_e(Decimal('40800000000.00000000000000'))
# '4.08E+10'

format_e(Decimal('40000000000.00000000000000'))
# '4E+10'

format_e(Decimal('40812300000.00000000000000'))
# '4.08123E+10'
142
votes

Here's an example using the format() function:

>>> "{:.2E}".format(Decimal('40800000000.00000000000000'))
'4.08E+10'

Instead of format, you can also use f-strings:

>>> f"{Decimal('40800000000.00000000000000'):.2E}"
'4.08E+10'
45
votes

Given your number

x = Decimal('40800000000.00000000000000')

Starting from Python 3,

'{:.2e}'.format(x)

is the recommended way to do it.

e means you want scientific notation, and .2 means you want 2 digits after the dot. So you will get x.xxe±n.

39
votes

No one mentioned the short form of the .format method:

Needs at least Python 3.6

f"{Decimal('40800000000.00000000000000'):.2E}"

(I believe it's the same as Cees Timmerman, just a bit shorter)

11
votes

See tables from Python string formatting to select the proper format layout. In your case it's %.2E.

11
votes

This is a consolidated list of the "Simple" Answers & Comments.

PYTHON 3

from decimal import Decimal

x = '40800000000.00000000000000'
# Converted to Float
x = Decimal(x)

# ===================================== # `Dot Format`
print("{0:.2E}".format(x))
# ===================================== # `%` Format
print("%.2E" % x)
# ===================================== # `f` Format
print(f"{x:.2E}")
# =====================================
# ALL Return: 4.08E+10
print((f"{x:.2E}") == ("%.2E" % x) == ("{0:.2E}".format(x)))
# True
print(type(f"{x:.2E}") == type("%.2E" % x) == type("{0:.2E}".format(x)))
# True
# =====================================

OR Without IMPORT's

# NO IMPORT NEEDED FOR BASIC FLOATS
y = '40800000000.00000000000000'
y = float(y)

# ===================================== # `Dot Format`
print("{0:.2E}".format(y))
# ===================================== # `%` Format
print("%.2E" % y)
# ===================================== # `f` Format
print(f"{y:.2E}")
# =====================================
# ALL Return: 4.08E+10
print((f"{y:.2E}") == ("%.2E" % y) == ("{0:.2E}".format(y)))
# True
print(type(f"{y:.2E}") == type("%.2E" % y) == type("{0:.2E}".format(y)))
# True
# =====================================

Comparing

# =====================================
x
# Decimal('40800000000.00000000000000')
y
# 40800000000.0

type(x)
# <class 'decimal.Decimal'>
type(y)
# <class 'float'>

x == y
# True
type(x) == type(y)
# False

x
# Decimal('40800000000.00000000000000')
y
# 40800000000.0

So for Python 3, you can switch between any of the three for now.

My Fav:

print("{0:.2E}".format(y))
4
votes

My decimals are too big for %E so I had to improvize:

def format_decimal(x, prec=2):
    tup = x.as_tuple()
    digits = list(tup.digits[:prec + 1])
    sign = '-' if tup.sign else ''
    dec = ''.join(str(i) for i in digits[1:])
    exp = x.adjusted()
    return '{sign}{int}.{dec}e{exp}'.format(sign=sign, int=digits[0], dec=dec, exp=exp)

Here's an example usage:

>>> n = decimal.Decimal(4.3) ** 12314
>>> print format_decimal(n)
3.39e7800
>>> print '%e' % n
inf
4
votes

This worked best for me:

import decimal
'%.2E' % decimal.Decimal('40800000000.00000000000000')
# 4.08E+10
3
votes

To convert a Decimal to scientific notation without needing to specify the precision in the format string, and without including trailing zeros, I'm currently using

def sci_str(dec):
    return ('{:.' + str(len(dec.normalize().as_tuple().digits) - 1) + 'E}').format(dec)

print( sci_str( Decimal('123.456000') ) )    # 1.23456E+2

To keep any trailing zeros, just remove the normalize().

3
votes

I prefer Python 3.x way.

cal = 123.4567
print(f"result {cal:.4E}")

4 indicates how many digits are shown shown in the floating part.

cal = 123.4567
totalDigitInFloatingPArt = 4
print(f"result {cal:.{totalDigitInFloatingPArt}E} ")
1
votes

Here is the simplest one I could find.

format(40800000000.00000000000000, '.2E')
#'4.08E+10'

('E' is not case sensitive. You can also use '.2e')

0
votes
def formatE_decimal(x, prec=2):
    """ Examples:
    >>> formatE_decimal('0.1613965',10)
    '1.6139650000E-01'
    >>> formatE_decimal('0.1613965',5)
    '1.61397E-01'
    >>> formatE_decimal('0.9995',2)
    '1.00E+00'
    """
    xx=decimal.Decimal(x) if type(x)==type("") else x 
    tup = xx.as_tuple()
    xx=xx.quantize( decimal.Decimal("1E{0}".format(len(tup[1])+tup[2]-prec-1)), decimal.ROUND_HALF_UP )
    tup = xx.as_tuple()
    exp = xx.adjusted()
    sign = '-' if tup.sign else ''
    dec = ''.join(str(i) for i in tup[1][1:prec+1])   
    if prec>0:
        return '{sign}{int}.{dec}E{exp:+03d}'.format(sign=sign, int=tup[1][0], dec=dec, exp=exp)
    elif prec==0:
        return '{sign}{int}E{exp:+03d}'.format(sign=sign, int=tup[1][0], exp=exp)
    else:
        return None