247

How can I display 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.

Freddy Mcloughlan
  • 4,129
  • 1
  • 13
  • 29
Greg
  • 45,306
  • 89
  • 231
  • 297
  • 3
    kinda doubleposting, you could have used this topic you just started: http://stackoverflow.com/questions/6913166/django-how-to-display-scientific-notation-on-admin-page-field – Samuele Mattiuzzo Aug 02 '11 at 14:20
  • 39
    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 Aug 02 '11 at 14:26

13 Answers13

220
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'
ABM
  • 1,628
  • 2
  • 26
  • 42
eumiro
  • 207,213
  • 34
  • 299
  • 261
  • 26
    As an aside, despite the `format % values` syntax still being used even within the Python 3 standard library, I believe it's technically deprecated in Python 3, or at least not the recommended formatting method, and the current recommended syntax, starting with Python 2.6, would be `'{0:.2E}'.format(Decimal('40800000000.00000000000000'))` (or `'{:.2E}'` in Python 2.7+). While not strictly useful for this situation, due to the additional characters for no added functionality, `str.format` does allow for more complex mixing/rearranging/reutilizing of format arguments. – JAB Aug 02 '11 at 14:42
  • 4
    @CharlieParker Use [`format`](https://stackoverflow.com/a/19864272/365102). It's more *jazzy*. – Mateen Ulhaq Feb 05 '18 at 21:26
180

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'
jaquinocode
  • 634
  • 7
  • 12
Cees Timmerman
  • 17,623
  • 11
  • 91
  • 124
72

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

patapouf_ai
  • 17,605
  • 13
  • 92
  • 132
48

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)

Eulenfuchswiesel
  • 879
  • 9
  • 20
  • 6
    Should be accepted answer. f-strings is the future of python string formatting :) – Gandalf Saxe Nov 19 '18 at 11:13
  • 4
    As an fyi to future readers like myself: if you don't care to control the number of digits and don't mind floating point errors, you can simply use `{num:E}`, where e.g. num = 40800000000.00000000000000 – shayaan Feb 26 '19 at 08:16
  • 1
    For information about formatting https://stackoverflow.com/questions/45310254/fixed-digits-after-decimal-with-f-strings#45310389 – Eulenfuchswiesel Aug 25 '20 at 16:49
  • Following on from shayaan's recommendation that is f"{num:E}" – user160623 May 27 '23 at 15:09
18

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))
JayRizzo
  • 3,234
  • 3
  • 33
  • 49
12

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

Mihai Maruseac
  • 20,967
  • 7
  • 57
  • 109
5

This worked best for me:

import decimal
'%.2E' % decimal.Decimal('40800000000.00000000000000')
# 4.08E+10
Matthew Fitch
  • 245
  • 1
  • 9
  • 13
4

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
ubershmekel
  • 11,864
  • 10
  • 72
  • 89
  • 3
    Just `"{:.2e}".format(n)` returns `'3.39e+7800'` in Python 3.3.2 (v3.3.2:d047928ae3f6, May 16 2013, 00:06:53) [MSC v.1600 64 bit (AMD64)] on win32. – Cees Timmerman Nov 08 '13 at 16:52
4

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().

MikeM
  • 13,156
  • 2
  • 34
  • 47
3

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} ")
2

Adding an updated answer to show how to apply e notation to small numbers only

value = 0.1
a = "{:,}".format(value) if value >= 0.001 else "{:,.3e}".format(value)
print(a) # 0.1

value = 0.00002488
a = "{:,}".format(value) if value >= 0.001 else "{:,.3e}".format(value)
print(a) # 2.488e-05
Beppe C
  • 11,256
  • 2
  • 19
  • 41
1

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
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
Andrej
  • 1
  • 1