Como posso formatar um decimal para sempre mostrar duas casas decimais?

237

Eu quero exibir:

49 Como 49.00

e:

54.9 Como 54.90

Independentemente do comprimento do decimal ou se existem casas decimais, eu gostaria de exibir um Decimalcom 2 casas decimais e gostaria de fazê-lo de maneira eficiente. O objetivo é exibir valores monetários.

por exemplo, 4898489.00

orokusaki
fonte
4
Você precisa que seja o maior tempo possível? O que isso significa? Você pode adicionar zeros à esquerda até que você ficar sem memória, mas eu suspeito que não é o que você quer ...
Mark Byers
Suponho que isso possa significar que o OP está usando decimal.Decimal e está insatisfeito com a precisão do contexto decimal que limita a precisão a n dígitos como em "n dígitos de precisão no sentido estrito" (por exemplo, '123.456' se torna decimal ('1.2E + 2 ')) e não "n dígitos na parte fracionária" (para Decimal (' 123.45 ')) ... Veja minha resposta para tentar ajudar com isso. ;-)
Michał Marczyk
1
Sim, eles são para valores monetários.
precisa saber é o seguinte

Respostas:

105

Suponho que você provavelmente esteja usando os Decimal()objetos do decimalmódulo? (Se você precisar exatamente de dois dígitos de precisão além do ponto decimal com números arbitrariamente grandes, você definitivamente deveria ser, e é isso que o título da sua pergunta sugere ...)

Nesse caso, a seção Perguntas frequentes decimais dos documentos possui um par de perguntas / respostas que pode ser útil para você:

P. Em um aplicativo de ponto fixo com duas casas decimais, algumas entradas têm muitas casas e precisam ser arredondadas. Outros não devem ter dígitos em excesso e precisam ser validados. Quais métodos devem ser usados?

A. O método quantize () arredonda para um número fixo de casas decimais. Se a armadilha Inexact estiver definida, também será útil para validação:

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

A próxima pergunta é:

P. Depois de validar duas entradas de local, como mantenho essa invariável em um aplicativo?

Se você precisar de uma resposta para isso (junto com muitas outras informações úteis), consulte a seção acima mencionada dos documentos . Além disso, se você mantiver seus Decimals com dois dígitos de precisão além do ponto decimal (significando a precisão necessária para manter todos os dígitos à esquerda do ponto decimal e dois à direita dele e não mais ...), convertê-los em strings com strfuncionará bem:

str(Decimal('10'))
# -> '10'
str(Decimal('10.00'))
# -> '10.00'
str(Decimal('10.000'))
# -> '10.000'
Michał Marczyk
fonte
2
Ah, esqueci de mencionar eficiência na resposta ... mas acho que não sou especialista de qualquer maneira. Não vejo razão para que seja particularmente ineficiente manter um número fixo de "dígitos fracionários" por perto - embora qualquer operação executada nos números possa exigir uma operação de arredondamento no resultado para alinhar os requisitos ... eficiência, isso provavelmente deve ser feito com a menor frequência possível - como antes da serialização / impressão para o usuário.
Michał Marczyk
517

Você deve usar as novas especificações de formato para definir como seu valor deve ser representado:

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

A documentação pode ser um pouco obtusa às vezes, por isso recomendo as seguintes referências legíveis e mais fáceis:

O Python 3.6 introduziu a interpolação literal de strings (também conhecida como strings-f), agora você pode escrever o texto acima ainda mais sucinto como:

>>> f'{pi:.2f}'
'3.14'
BioGeek
fonte
4
@Droogans: Euh ... formatretorna um str, não um float: print type({0:.2f}".format(pi))retorna <type 'str'>.
BioGeek
Opa Verbo sobrecarregando a palavra return. Mude mentalmente isso para prints.
Droogans
20
Se você não quiser usar o espaço reservado numérico:"{:.2f}".format(pi)
Usuário
O que 0:faz? Presumo que o .faz parte da cadeia de caracteres python
information_interchange
135

A seção Operações de formatação de string da documentação do Python contém a resposta que você está procurando. Em resumo:

"%0.2f" % (num,)

Alguns exemplos:

>>> "%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'
Travis Bradshaw
fonte
Não há necessidade de 0depois do %, e não há necessidade de envolver numum tuple.
precisa saber é o seguinte
17
Na verdade, quebra automática de num em uma tupla é uma convenção de codificação para evitar um erro de digitação de pato nos argumentos durante a formatação da string. Nesse caso, não tem nenhum efeito com uma conversão flutuante, mas evita um erro inesperado de tipo ao converter para seqüências de caracteres. Considere r = 1; "%s" % r; r = (1, 2); "%s" % rversus r = 1; "%s" % (r,); r = (1,2 ); "%s" % (r,). Como tal, os estilos de codificação mais sofisticados do python usam a tupla incondicional agora (e o Python 3 reprovou todo o método de formatação de strings como propenso a erros).
Travis Bradshaw
Além disso, como um cara com formação em matemática, a notação decimal "nua" é feia. O 0 principal não faz mal a nada e parece melhor. :)
Travis Bradshaw
3
Esteticamente não é diferente. Mais importante ainda, o 0 é o valor padrão. Não há absolutamente nenhum mal em fornecer o padrão, se criar um código esteticamente agradável. É interessante quantos desenvolvedores optam por não diferenciar entre correção e estilo. : /
Travis Bradshaw /
32

Você pode usar o operador de formatação de string da seguinte maneira:

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

Não sei ao certo o que você quer dizer com "eficiente" - esse certamente não é o gargalo do seu aplicativo. Se o seu programa estiver sendo executado lentamente, analise-o primeiro para encontrar os pontos de acesso e depois otimize-os.

Adam Rosenfield
fonte
1
Eu acho que a variável chamada 'f' pode confundir algumas pessoas. Melhor chamar de outra coisa para um exemplo como Travis abaixo.
Aleck Landgraf
28
>>> print "{:.2f}".format(1.123456)
1.12

Você pode mudar 2em 2fqualquer número de casas decimais que você deseja mostrar.

EDITAR:

De Python3.6, isso se traduz em:

>>> print(f"{1.1234:.2f}")
1.12
Aziz Alto
fonte
19

.format é uma maneira mais legível de lidar com formatação variável:

'{:.{prec}f}'.format(26.034, prec=2)
Mayank Patel
fonte
18

No python 3, uma maneira de fazer isso seria

'{:.2f}'.format(number)
Devin Ersoy
fonte
6

se você tiver vários parâmetros, poderá usar

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

Se você estiver usando isso para moeda, e também quiser que o valor seja separado por ,você, use

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

por exemplo:

currency_value = 1234.50

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

Aqui está um pouco do código que escrevi há algum tempo:

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
3kstc
fonte
0

O exemplo da maneira mais fácil de mostrar como fazer isso é:

Código:

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

Saída: Respostas corretas: 88,64%

SHARON KERKETTA 1741050
fonte
-6

A respeito

print round(20.2564567 , 2)    >>>>>>>        20.25


print round(20.2564567 , 4)    >>>>>>>        20.2564
Mahmoud Hamdy
fonte