Como arredondar para 2 casas decimais com Python?

254

Estou recebendo muitas casas decimais na saída desse código (conversor de Fahrenheit para Celsius).

Meu código atualmente é assim:

def main():
    printC(formeln(typeHere()))

def typeHere():
    global Fahrenheit
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(c):
    Celsius = (Fahrenheit - 32.00) * 5.00/9.00
    return Celsius

def printC(answer):
    answer = str(answer)
    print "\nYour Celsius value is " + answer + " C.\n"



main()

Portanto, minha pergunta é: como faço para o programa arredondar todas as respostas para a segunda casa decimal?

Dolcens
fonte
6
Uma pequena observação sobre o seu código. Não há razão para manter o valor de Fahrenheit como global; basta (e melhor) transmiti-lo como parâmetro para suas funções. Portanto, remova a linha "Fahrenheit global". Na função formeln, renomeie o parâmetro para a função "Fahreinheit" formeln (Fahreinheit). Quanto ao arredondamento, você pode apenas usar os parâmetros "%" para exibir apenas os 2 primeiros dígitos, e deve ser arredondado para esses dígitos. Não há efeito no número de dígitos fornecido na fórmula no formulário.
Arieli

Respostas:

443

Você pode usar a roundfunção, que usa como primeiro argumento o número e o segundo argumento é a precisão após o ponto decimal.

No seu caso, seria:

answer = str(round(answer, 2))
rolisz
fonte
21
Isso é chamado arredondamento de banqueiros. Arredonda para o número par. Está no padrão IEEE 754 para números de ponto flutuante. en.wikipedia.org/wiki/Rounding#Round_half_to_even
rolisz
37
Não sei ao certo o que levou as pessoas a votarem no comentário acima. Para que conste, o fato de round(2.675, 2)dar 2.67e não 2.68ter nada a ver com o arredondamento de Banker.
Marque 'Dickinson
3
nota : isso altera o valor da resposta. Se você simplesmente deseja arredondar para exibição, vá com a resposta de @Johnsyweb - stackoverflow.com/a/20457284/1498405
hardmooth
4
@Johnsyweb Estou tentando hoje, ano após o post original e parece funcionar como esperado. Parece que round () evoluiu com o tempo. Veja abaixo: round (1.379, 2) -> 1.38 round (1.372, 2) -> 1.37 round (1.375, 2) -> 1.38
NightFurry
82

Usando str.format()a sintaxe para exibir answer com duas casas decimais (sem alterar o valor subjacente de answer):

def printC(answer):
    print("\nYour Celsius value is {:0.2f}ºC.\n".format(answer))

Onde:

  • :apresenta a especificação de formato
  • 0 permite preenchimento zero com reconhecimento de sinal para tipos numéricos
  • .2define a precisão para2
  • f exibe o número como um número de ponto fixo
Johnsyweb
fonte
3
Esta é a resposta mais útil para IMO - mantém intacto o valor real e é simples de implementar! Obrigado!
BrettJ
Não sei por que, mas o formato '{: 0.2f}'. (0,5357706) me fornece '0,54' (python 3.6)
Noam Peled
3
@NoamPeled: Por que não deveria? 0.5357...está mais próximo do 0.54que 0.53, portanto, arredondar para 0.54fazer sentido.
ShadowRanger
"{:0.2f}".format(1.755)-> 1,75 "{:0.2f}".format(1.7551)-> 1,76 - No entanto, eu esperava que ambos fossem iguais a 1,76.
Janothan
(Versão do Python: 3.6.10)
Janothan 5/03
48

A maioria das respostas sugeridas roundou format. roundàs vezes é arredondado para cima e, no meu caso, eu precisava que o valor da minha variável fosse arredondado para baixo e não apenas exibido como tal.

round(2.357, 2)  # -> 2.36

Encontrei a resposta aqui: Como arredondar um número de ponto flutuante até uma determinada casa decimal?

import math
v = 2.357
print(math.ceil(v*100)/100)  # -> 2.36
print(math.floor(v*100)/100)  # -> 2.35

ou:

from math import floor, ceil

def roundDown(n, d=8):
    d = int('1' + ('0' * d))
    return floor(n * d) / d

def roundUp(n, d=8):
    d = int('1' + ('0' * d))
    return ceil(n * d) / d
s4w3d0ff
fonte
1
Eu votei - era isso que eu estava procurando; Eu gosto do seu trabalho com o python-poloniex: D
Skylar Saveland
2
"os valores são arredondados para o múltiplo mais próximo de 10 para a potência menos ndigits;" docs.python.org/3/library/functions.html#round por isso não, redondo nem sempre se volta, por exemploround(2.354, 2) # -> 2.35
Pete Kirkham
@PeteKirkham você está certo, editei minha resposta para fazer mais sentido e precisão.
S4w3d0ff
2
-0.54 é a resposta correta para o arredondamento -,5357706 para baixo porque é um número negativo, -0,54 <-0.53
s4w3d0ff
2
Eu usaria em 10**dvez de int('1' + ('0' * d)).
Jonathon Reinhart
11
float(str(round(answer, 2)))
float(str(round(0.0556781255, 2)))
Mahadi
fonte
8

Você quer arredondar sua resposta.

round(value,significantDigit)é a solução comum para fazer isso, no entanto, às vezes, isso não funciona como seria de esperar de uma perspectiva matemática quando o dígito imediatamente inferior (à esquerda) ao dígito para o qual você está arredondando possui a 5.

Aqui estão alguns exemplos desse comportamento imprevisível:

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

Supondo que sua intenção seja fazer o arredondamento tradicional para estatísticas nas ciências, este é um invólucro útil para que a roundfunção funcione conforme o esperado, necessitando de importcoisas extras Decimal.

>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*6),2)

0.08

Aha! Então, com base nisso, podemos fazer uma função ...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

Basicamente, isso adiciona um valor muito pequeno à string para forçá-la a arredondar corretamente nas instâncias imprevisíveis em que ela normalmente não roundfunciona com a função quando você espera. Um valor conveniente a acrescentar é 1e-Xonde Xestá o comprimento da sequência numérica que você está tentando usar roundno plus 1.

A abordagem do uso 10**(-len(val)-1)foi deliberada, pois é o maior número pequeno que você pode adicionar para forçar a mudança, além de garantir que o valor adicionado nunca mude o arredondamento, mesmo que o decimal .esteja ausente. Eu poderia usar apenas 10**(-len(val))um condicional if (val>1)para subtrair 1mais ... mas é mais simples sempre subtrair o valor, 1pois isso não mudará muito o intervalo aplicável de números decimais que esta solução alternativa pode manipular adequadamente. Essa abordagem falhará se seus valores atingirem os limites do tipo, isso falhará, mas, para quase todo o intervalo de valores decimais válidos, deve funcionar.

Portanto, o código final será algo como:

def main():
    printC(formeln(typeHere()))

def roundTraditional(val,digits):
    return round(val+10**(-len(str(val))-1))

def typeHere():
    global Fahrenheit
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(c):
    Celsius = (Fahrenheit - 32.00) * 5.00/9.00
    return Celsius

def printC(answer):
    answer = str(roundTraditional(answer,2))
    print "\nYour Celsius value is " + answer + " C.\n"

main()

... deve fornecer os resultados esperados.

Você também pode usar a biblioteca decimal para fazer isso, mas o invólucro que proponho é mais simples e pode ser preferido em alguns casos.


Edit: Obrigado Blckknght por apontar que a 5caixa de franja ocorre apenas para determinados valores aqui .

Jason R. Mick
fonte
6

Basta usar a formatação com% .2f, que permite arredondar para 2 casas decimais.

def printC(answer):
    print "\nYour Celsius value is %.2f C.\n" % answer
Santosh Ghimire
fonte
4

Você pode usar o operador de formatação de string do python "%". "% .2f" significa 2 dígitos após o ponto decimal.

def typeHere():
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(Fahrenheit):
    Celsius = (Fahrenheit - 32.0) * 5.0/9.0
    return Celsius

def printC(answer):
    print "\nYour Celsius value is %.2f C.\n" % answer

def main():
    printC(formeln(typeHere()))

main()

http://docs.python.org/2/library/stdtypes.html#string-formatting

arieli
fonte
4

Você pode usar o operador redondo para até 2 casas decimais

num = round(343.5544, 2)
print(num) // output is 343.55
Asad Manzoor
fonte
3

Você pode usar a função round.

round(80.23456, 3)

lhe dará uma resposta de 80.234

No seu caso, use

answer = str(round(answer, 2))

Espero que isto ajude :)

Satyaki Sanyal
fonte
2

Se você precisar evitar problemas de ponto flutuante nos números de arredondamento para contabilidade, poderá usar a arredondamento numpy.

Você precisa instalar o numpy:

pip install numpy

e o código:

import numpy as np

print(round(2.675, 2))
print(float(np.round(2.675, 2)))

impressões

2.67
2.68

Você deve usar isso se gerenciar dinheiro com arredondamento legal.

Samuel Dauzon
fonte
1

Aqui está um exemplo que eu usei:

def volume(self):
    return round(pi * self.radius ** 2 * self.height, 2)

def surface_area(self):
    return round((2 * pi * self.radius * self.height) + (2 * pi * self.radius ** 2), 2)
Patrick Hill
fonte
1

Não sei por que, mas o formato '{: 0.2f}'. (0,5357706) me fornece '0,54'. A única solução que funciona para mim (python 3.6) é a seguinte:

def ceil_floor(x):
    import math
    return math.ceil(x) if x < 0 else math.floor(x)

def round_n_digits(x, n):
    import math
    return ceil_floor(x * math.pow(10, n)) / math.pow(10, n)

round_n_digits(-0.5357706, 2) -> -0.53 
round_n_digits(0.5357706, 2) -> 0.53
Noam Peled
fonte
Isso é truncante, não arredondado.
ShadowRanger