Как я могу отформатировать десятичное число, чтобы всегда отображать 2 десятичных знака?


237

Я хочу отобразить:

49 так как 49.00

и:

54.9 так как 54.90

Независимо от длины десятичного разделителя или наличия десятичных разрядов, я хотел бы отобразить Decimalс двумя десятичными разрядами, и я хотел бы сделать это эффективным способом. Цель состоит в том, чтобы отобразить денежные значения.

например, 4898489.00


4
Вам нужно, чтобы это было как можно дольше? Что это значит? Вы можете добавлять начальные нули, пока у вас не закончится память, но я подозреваю, что это не то, что вы хотите ...
Марк Байерс

Я предполагаю, что это может означать, что OP использует decimal.Decimal и недоволен точностью десятичного контекста, которая ограничивает точность до n цифр, как в «n цифрах точности в строгом смысле» (например, «123.456» становится десятичным («1.2E +»). 2 ')), а не "n цифр в дробной части" (для десятичной дроби (' 123.45 '))) ... Смотрите мой ответ, чтобы попытаться помочь с этим. ;-)
Михал Марчик

1
Да, они для денежных ценностей.
orokusaki

Ответы:


105

Я полагаю, вы, вероятно, используете Decimal()объекты из decimalмодуля? (Если вам нужно ровно две цифры точности после десятичной запятой с произвольно большими числами, вам определенно следует это сделать, и именно об этом говорит заголовок вашего вопроса ...)

Если это так, в разделе « Десятичные вопросы и ответы » в документации есть пара вопросов / ответов, которая может быть полезна для вас:

В. В приложении с фиксированной запятой с двумя десятичными знаками некоторые входные данные имеют много мест и должны быть округлены. Другие не должны иметь избыточных цифр и должны быть проверены. Какие методы следует использовать?

A. Метод quantize () округляет до фиксированного числа десятичных разрядов. Если установлена ​​ловушка Inexact, это также полезно для проверки:

>>> TWOPLACES = Decimal(10) ** -2       # same as Decimal('0.01')
>>> # Round to two places
>>> Decimal('3.214').quantize(TWOPLACES)
Decimal('3.21')
>>> # Validate that a number does not exceed two places
>>> Decimal('3.21').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Decimal('3.21')
>>> Decimal('3.214').quantize(TWOPLACES, context=Context(traps=[Inexact]))
Traceback (most recent call last):
   ...
Inexact: None

Следующий вопрос гласит

В. Как только у меня есть действительные двухместные входные данные, как мне сохранить этот инвариант в приложении?

Если вам нужен ответ на этот вопрос (наряду с множеством другой полезной информации), см. Вышеупомянутый раздел документации . Кроме того, если вы сохраняете свои Decimals с двумя цифрами точности после десятичной запятой (то есть настолько, насколько это необходимо, чтобы все цифры оставались слева от десятичной запятой и две справа от нее и не более ...), тогда преобразование их в строки с strбудет работать нормально:

str(Decimal('10'))
# -> '10'
str(Decimal('10.00'))
# -> '10.00'
str(Decimal('10.000'))
# -> '10.000'

2
О, забыл упомянуть эффективность в ответе ... но я все равно не эксперт. Я не вижу причин, почему было бы особенно неэффективно хранить вокруг себя фиксированное число «дробных цифр» - хотя любые операции, выполняемые над числами, могут потребовать операции округления результата, чтобы привести его в соответствие с требованиями ... Для Ради эффективности, это, вероятно, следует делать как можно реже - как раз перед сериализацией / распечаткой для пользователя.
Михал Марчик

517

Вы должны использовать новые спецификации формата, чтобы определить, как должно быть представлено ваше значение:

>>> from math import pi  # pi ~ 3.141592653589793
>>> '{0:.2f}'.format(pi)
'3.14'

Временами документация может быть немного тупой, поэтому я рекомендую следующие, более удобочитаемые ссылки:

В Python 3.6 введена интерполяция литеральных строк (также называемая f-строками), так что теперь вы можете написать выше еще более кратко:

>>> f'{pi:.2f}'
'3.14'

4
@Droogans: Euh ... formatдействительно возвращает, а strне float: print type({0:.2f}".format(pi))возвращает <type 'str'>.
BioGeek

К сожалению. Глагол перегружает слово return. Пожалуйста, мысленно измените это на prints.
Droogans

20
Если вы не хотите использовать числовой заполнитель:"{:.2f}".format(pi)
Пользователь

Что делает 0:? Я предполагаю, что .является частью строки Python
information_interchange

135

Раздел « Операции форматирования строки» документации Python содержит ответ, который вы ищете. Коротко:

"%0.2f" % (num,)

Некоторые примеры:

>>> "%0.2f" % 10
'10.00'
>>> "%0.2f" % 1000
'1000.00'
>>> "%0.2f" % 10.1
'10.10'
>>> "%0.2f" % 10.120
'10.12'
>>> "%0.2f" % 10.126
'10.13'

Там нет необходимости для 0после %, и нет необходимости, чтобы обернуть numв tuple.
user238424

17
На самом деле, обертка num в кортеже - это соглашение о кодировании, чтобы предотвратить ошибку при вводе утки в аргументы во время форматирования строки. Это не имеет никакого эффекта в этом случае с преобразованием с плавающей запятой, но это предотвращает непредвиденную ошибку типа при преобразовании в строки. Рассмотрим r = 1; "%s" % r; r = (1, 2); "%s" % rпротив r = 1; "%s" % (r,); r = (1,2 ); "%s" % (r,). Таким образом, большинство сложных стилей кодирования в Python теперь используют безусловный кортеж (и Python 3 исключил весь метод форматирования строк как подверженный ошибкам).
Трэвис Брэдшоу

Также, как парень с математическим фоном, «голые» десятичные обозначения уродливы. Ведущий 0 ничего не ранит и выглядит лучше. :)
Трэвис Брэдшоу

3
Эстетически ничем не отличается. Самое главное, 0 - это значение по умолчанию, в любом случае. Там нет абсолютно никакого вреда в предоставлении по умолчанию, если это делает для эстетически приятного кода. Интересно, сколько разработчиков предпочитают не (не могут?) Различать правильность и стиль. : /
Трэвис Брэдшоу

32

Вы можете использовать оператор форматирования строки следующим образом:

num = 49
x = "%.2f" % num  # x is now the string "49.00"

Я не уверен, что вы подразумеваете под «эффективными» - это почти наверняка не является узким местом вашего приложения. Если ваша программа работает медленно, сначала профилируйте ее, чтобы найти горячие точки, а затем оптимизируйте их.


1
Я думаю, что переменная с именем 'f' может запутать некоторых людей. Лучше назвать это как-то еще для примера, подобного Трэвису ниже.
Алек Ландграф

28
>>> print "{:.2f}".format(1.123456)
1.12

Вы можете изменить 2в 2fлюбое количество знаков после запятой , которые вы хотите показать.

РЕДАКТИРОВАТЬ:

От Python3.6это переводится как:

>>> print(f"{1.1234:.2f}")
1.12



6

если у вас есть несколько параметров, вы можете использовать

 print('some string {0:.2f} & {1:.2f}'.format(1.1234,2.345))
 >>> some string 1.12 & 2.35

3

Если вы используете это для валюты, а также хотите, чтобы значение было разделено на ,s, вы можете использовать

$ {:,.f2}.format(currency_value),

например:

currency_value = 1234.50

$ {:,.f2}.format(currency_value) --> $ 1,234.50

Вот немного кода, который я написал некоторое время назад:

print("> At the end of year " + year_string + " total paid is \t$ {:,.2f}".format(total_paid))

> At the end of year   1  total paid is         $ 43,806.36
> At the end of year   2  total paid is         $ 87,612.72
> At the end of year   3  total paid is         $ 131,419.08
> At the end of year   4  total paid is         $ 175,225.44
> At the end of year   5  total paid is         $ 219,031.80   <-- Note .80 and not .8
> At the end of year   6  total paid is         $ 262,838.16
> At the end of year   7  total paid is         $ 306,644.52
> At the end of year   8  total paid is         $ 350,450.88
> At the end of year   9  total paid is         $ 394,257.24
> At the end of year  10  total paid is         $ 438,063.60   <-- Note .60 and not .6
> At the end of year  11  total paid is         $ 481,869.96
> At the end of year  12  total paid is         $ 525,676.32
> At the end of year  13  total paid is         $ 569,482.68
> At the end of year  14  total paid is         $ 613,289.04
> At the end of year  15  total paid is         $ 657,095.40   <-- Note .40 and not .4  
> At the end of year  16  total paid is         $ 700,901.76
> At the end of year  17  total paid is         $ 744,708.12
> At the end of year  18  total paid is         $ 788,514.48
> At the end of year  19  total paid is         $ 832,320.84
> At the end of year  20  total paid is         $ 876,127.20   <-- Note .20 and not .2

0

Самый простой пример, который покажет вам, как это сделать:

Код:

>>> points = 19.5 >>> total = 22 >>>'Correct answers: {:.2%}'.format(points/total) `

Вывод: правильных ответов: 88,64%


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.