Отобразить десятичную дробь в научной записи

161

Как я могу отобразить это:

Десятичное число ('40800000000.00000000000000') как '4.08E + 10'?

Я пробовал это:

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

Но у него есть те дополнительные 0.

Greg
источник
3
вроде двойной записи, вы могли бы использовать эту тему, которую только что начали: stackoverflow.com/questions/6913166/…
Самуэль Маттиуццо
13
нет, совсем нет Я хотел разделить это на простой вопрос (как это сделать в Python) и сложный, неясный вопрос, на который, я сомневаюсь, кто-нибудь ответит (как это сделать в Django). Обратите внимание, что на это уже есть ответ. Теперь я на полпути к своему окончательному ответу вместо 0%, если я разместил их вместе. Кроме того, разделение вопросов облегчает людям поиск ответов. Например, если Боб ищет вопрос о десятичном форматировании, он может пропустить SO-квест с Джанго в заголовке.
Грег
да, это было только для моего интереса: P легче следовать одной нити. в основном это похоже на мой ответ (только немного более конкретный). я тоже надеюсь получить ответ от Django.
Самуэль Маттиуццо

Ответы:

157
from decimal import Decimal

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

# returns '4.08E+10'

В ваших «40800000000.00000000000000» есть много более значимых нулей, которые имеют то же значение, что и любая другая цифра. Вот почему вы должны четко указать, где вы хотите остановиться.

Если вы хотите удалить все конечные нули автоматически, вы можете попробовать:

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
источник
22
Кроме того, несмотря на то, что format % valuesсинтаксис все еще используется даже в стандартной библиотеке Python 3, я считаю, что он технически устарел в Python 3 или, по крайней мере, не рекомендуемый метод форматирования, и текущий рекомендуемый синтаксис, начиная с Python 2.6, будет '{0:.2E}'.format(Decimal('40800000000.00000000000000'))( или '{:.2E}'в Python 2.7+). Хотя это не совсем полезно для этой ситуации, из-за дополнительных символов для отсутствия дополнительной функциональности, str.formatэто позволяет более сложное смешивание / перестановка / повторное использование аргументов формата.
JAB
как насчет питона 3?
Чарли Паркер
4
@CharlieParker Использовать format. Это более джазово .
Матин Улхак
121

Вот пример использования format()функции:

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

Вместо формата вы также можете использовать f-строки :

>>> f"{Decimal('40800000000.00000000000000'):.2E}"
'4.08E+10'
Сис Тиммерман
источник
3
Этот синтаксис также применяется к f-строкам в 3.6+f"{Decimal('40800000000.00000000000000'):.2E}"
Tritium21
37

Учитывая ваш номер

x = Decimal('40800000000.00000000000000')

Начиная с Python 3,

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

это рекомендуемый способ сделать это.

eозначает, что вы хотите научную запись, и .2означает, что вы хотите 2 цифры после точки. Так вы получитеx.xxE±n

patapouf_ai
источник
1
Смысл использования десятичной дроби состоит в том, чтобы получить точную и произвольную десятичную арифметику точности. Это не эквивалентно использованию поплавка.
asmeurer
@asmeurer Спасибо за разъяснения. Изменил мой ответ.
patapouf_ai
Есть ли способ вернуться от этого к плаванию?
Оленский
@olenscki только что float(x)сделает конвертацию x в float.
patapouf_ai
33

Никто не упомянул краткую форму .formatметода:

Требуется как минимум Python 3.6

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

(Я считаю, что это так же, как Сис Тиммерман, только немного короче)

Eulenfuchswiesel
источник
3
Должен быть принят ответ. f-strings - будущее форматирования строк Python :)
Гэндальф Сакс
1
Как для будущих читателей, таких как я: если вы не хотите контролировать число цифр и не {num:E}
обращаете
4

Мои десятичные числа слишком велики, %Eпоэтому мне пришлось импровизировать:

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)

Вот пример использования:

>>> n = decimal.Decimal(4.3) ** 12314
>>> print format_decimal(n)
3.39e7800
>>> print '%e' % n
inf
ubershmekel
источник
3
Просто "{:.2e}".format(n)возвращается '3.39e+7800'в Python 3.3.2 (v3.3.2: d047928ae3f6, 16 мая 2013, 00:06:53) [MSC v.1600 64 бит (AMD64)] на win32.
Сис Тиммерман
4

Это сработало лучше для меня:

import decimal
'%.2E' % decimal.Decimal('40800000000.00000000000000')
# 4.08E+10
Мэтью Фитч
источник
4

Это сводный список «простых» ответов и комментариев.

ПИТОН 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
# =====================================

ИЛИ Без 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
# =====================================

Сравнение

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

Так что для Python 3 вы можете переключаться между любыми из трех на данный момент.

Мой любимчик:

print("{0:.2E}".format(y))
JayRizzo
источник
3

Я предпочитаю Python 3.x способ.

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

4 указывает, сколько цифр показано в плавающей части.

cal = 123.4567
totalDigitInFloatingPArt = 4
print(f"result {cal:.{totalDigitInFloatingPArt}E} ")
ОСШ
источник
2

Чтобы преобразовать десятичную в научную нотацию без необходимости указывать точность в строке формата и без учета конечных нулей, я в настоящее время использую

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

Чтобы сохранить любые завершающие нули, просто удалите normalize().

MikeM
источник
1

Вот самый простой, который я смог найти.

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

('E' не чувствительна к регистру. Вы также можете использовать '.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
источник