Mostrar un decimal en notación científica

161

¿Cómo puedo mostrar esto?

¿Decimal ('40800000000.00000000000000') como '4.08E + 10'?

He intentado esto:

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

Pero tiene esos 0 extra.

Greg
fuente
3
un poco doble, podría haber usado este tema que acaba de comenzar: stackoverflow.com/questions/6913166/…
Samuele Mattiuzzo
13
no, en absoluto Quería separar esto en la pregunta fácil (cómo hacerlo en Python) y la pregunta difícil y oscura que dudo que alguien responda (cómo hacerlo en Django). Observe cómo esto ya tiene una respuesta. Ahora estoy a medio camino de mi respuesta final en lugar de 0% si los hubiera publicado juntos. Además de eso, separar las preguntas hace que sea más fácil para las personas buscar las respuestas. E., g si Bob está buscando una pregunta de formato decimal, puede saltear una búsqueda SO con Django en el título.
Greg
sí, fue solo para mi interés: P es más fácil seguir un hilo. básicamente es similar a mi respuesta (solo un "bit" más específico). Estoy esperando una respuesta de Django también, por cierto.
Samuele Mattiuzzo

Respuestas:

157
from decimal import Decimal

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

# returns '4.08E+10'

En su '40800000000.00000000000000' hay muchos ceros más significativos que tienen el mismo significado que cualquier otro dígito. Es por eso que tienes que decir explícitamente dónde quieres parar.

Si desea eliminar todos los ceros finales automáticamente, puede intentar:

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'
eumiro
fuente
22
Por otro lado, a pesar de que la format % valuessintaxis todavía se usa incluso dentro de la biblioteca estándar de Python 3, creo que está técnicamente en desuso en Python 3, o al menos no el método de formato recomendado, y la sintaxis recomendada actual, comenzando con Python 2.6, sería'{0:.2E}'.format(Decimal('40800000000.00000000000000')) ( o '{:.2E}'en Python 2.7+). Si bien no es estrictamente útil para esta situación, debido a los caracteres adicionales para no agregar funcionalidad, str.formatpermite una mezcla / reorganización / reutilización más compleja de los argumentos de formato.
JAB
¿Qué hay de Python 3?
Charlie Parker
44
@CharlieParker Use format . Es más jazzy .
Mateen Ulhaq
121

Aquí hay un ejemplo usando la format()función:

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

En lugar de formato, también puede usar cadenas f :

>>> f"{Decimal('40800000000.00000000000000'):.2E}"
'4.08E+10'
Cees Timmerman
fuente
3
Esta sintaxis también se aplica a las cadenas f en 3.6+f"{Decimal('40800000000.00000000000000'):.2E}"
Tritium21
37

Dado su número

x = Decimal('40800000000.00000000000000')

A partir de Python 3,

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

es la forma recomendada de hacerlo

esignifica que desea notación científica y .2quiere decir 2 dígitos después del punto. Entonces obtendrásx.xxE±n

patapouf_ai
fuente
1
El punto de usar Decimal es obtener aritmética decimal de precisión exacta y arbitraria. No es equivalente a usar un flotador.
asmeurer
@asmeurer Gracias por la aclaración. Cambié mi respuesta.
patapouf_ai
¿Hay alguna manera de regresar de esto para flotar?
olenscki
@olenscki solo haciendo float(x)convertirá x en flotante.
patapouf_ai
33

Nadie mencionó la forma abreviada del .formatmétodo:

Necesita al menos Python 3.6

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

(Creo que es lo mismo que Cees Timmerman, solo un poco más corto)

Eulenfuchswiesel
fuente
3
Se debe aceptar la respuesta. f-strings es el futuro del formato de cadenas de python :)
Gandalf Saxe
1
Como información para futuros lectores como yo: si no le importa controlar el número de dígitos y no le importan los errores de coma flotante, simplemente puede usar {num:E}, donde, por ejemplo, num = 40800000000.00000000000000
Shayaan
4

Mis decimales son demasiado grandes, %Easí que tuve que improvisar:

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)

Aquí hay un ejemplo de uso:

>>> n = decimal.Decimal(4.3) ** 12314
>>> print format_decimal(n)
3.39e7800
>>> print '%e' % n
inf
ubershmekel
fuente
3
Acaba de "{:.2e}".format(n)regresar '3.39e+7800'en Python 3.3.2 (v3.3.2: d047928ae3f6, 16 de mayo de 2013, 00:06:53) [MSC v.1600 64 bit (AMD64)] en win32.
Cees Timmerman el
4

Esto funcionó mejor para mí:

import decimal
'%.2E' % decimal.Decimal('40800000000.00000000000000')
# 4.08E+10
Matthew Fitch
fuente
4

Esta es una lista consolidada de las respuestas y comentarios "simples" .

PITÓN 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
# =====================================

O sin 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
# =====================================

Comparando

# =====================================
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

Entonces, para Python 3, puedes cambiar entre cualquiera de los tres por ahora.

Mi favorito:

print("{0:.2E}".format(y))
JayRizzo
fuente
3

Prefiero Python 3.x forma.

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

4 indica cuántos dígitos se muestran en la parte flotante.

cal = 123.4567
totalDigitInFloatingPArt = 4
print(f"result {cal:.{totalDigitInFloatingPArt}E} ")
snr
fuente
2

Para convertir un decimal a notación científica sin necesidad de especificar la precisión en la cadena de formato, y sin incluir ceros finales, actualmente estoy usando

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

Para mantener los ceros a la izquierda, simplemente elimine el normalize().

MikeM
fuente
1

Aquí está el más simple que pude encontrar.

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

('E' no distingue entre mayúsculas y minúsculas. También puede usar '.2e')

Rahat Ibrahim
fuente
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
fuente