Come arrotondare a 2 decimali con Python?


254

Sto ottenendo molti decimali nell'output di questo codice (convertitore da Fahrenheit a Celsius).

Il mio codice attualmente è simile al seguente:

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

Quindi la mia domanda è: come faccio ad arrotondare il programma a ogni risposta al secondo decimale?


6
Una piccola osservazione sul tuo codice. Non vi è alcun motivo per mantenere il valore di Fahrenheit come globale, è sufficiente (e migliore) trasmetterlo come parametro alle proprie funzioni. Quindi, rimuovere la riga "Global Fahrenheit". Nella funzione formeln, rinominare il parametro con la funzione "Fahreinheit" formeln (Fahreinheit). Per quanto riguarda l'arrotondamento, puoi semplicemente utilizzare i parametri "%" per visualizzare solo le prime 2 cifre e dovrebbe essere arrotondato per queste cifre. Non vi è alcun effetto sul numero di cifre fornite nella formula in formeln.
arieli,

Risposte:


443

È possibile utilizzare la roundfunzione, che assume come primo argomento il numero e il secondo argomento è la precisione dopo il punto decimale.

Nel tuo caso, sarebbe:

answer = str(round(answer, 2))


21
Questo si chiama arrotondamento dei banchieri. Arrotonda verso il numero pari. È nello standard IEEE 754 per i numeri in virgola mobile. en.wikipedia.org/wiki/Rounding#Round_half_to_even
rolisz

37
Non sono sicuro di cosa abbia indotto le persone a votare il commento sopra. Per la cronaca, il fatto che round(2.675, 2)2.67piuttosto che 2.68non ha nulla a che fare con l'arrotondamento del banchiere.
Mark Dickinson,

3
nota : questo cambia il valore della risposta. Se si vuole semplicemente giro per la visualizzazione, andare con la risposta di @Johnsyweb - stackoverflow.com/a/20457284/1498405
hardmooth

4
@Johnsyweb Lo sto provando oggi, un anno dopo il post originale e sembra funzionare come previsto. Sembra round () evoluto nel tempo. Vedi sotto: round (1.379, 2) -> 1.38 round (1.372, 2) -> 1.37 round (1.375, 2) -> 1.38
NightFurry

82

Utilizzando str.format()la sintassi per visualizzare answer con due cifre decimali (senza alterare il valore sottostante di answer):

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

Dove:

  • :introduce le specifiche del formato
  • 0 abilita il riempimento zero con riconoscimento dei segni per i tipi numerici
  • .2imposta la precisione su2
  • f visualizza il numero come un numero a virgola fissa

3
Questa è la risposta più utile IMO: mantiene intatto il valore reale ed è semplice da implementare! Grazie!
BrettJ il

Non so perché, ma il formato '{: 0.2f}' (0,5357706) mi dà '0,54' (pitone 3,6)
Noam Peled,

3
@NoamPeled: Perché non dovrebbe? 0.5357...è più vicino 0.54che a 0.53, quindi arrotondare per avere 0.54un senso.
ShadowRanger

"{:0.2f}".format(1.755)-> 1,75 "{:0.2f}".format(1.7551)-> 1,76 - Tuttavia, mi sarei aspettato entrambi pari a 1,76.
Janothan,

(Versione Python: 3.6.10)
Janothan

48

La maggior parte delle risposte suggerite roundoppure format. rounda volte arrotonda e nel mio caso avevo bisogno che il valore della mia variabile fosse arrotondato per difetto e non solo visualizzato come tale.

round(2.357, 2)  # -> 2.36

Ho trovato la risposta qui: come arrotondare un numero in virgola mobile fino a un determinato decimale?

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

o:

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

1
Ho votato - questo è quello che stavo cercando; Mi piace il tuo lavoro con python-poloniex: D
Skylar Saveland

2
"i valori sono arrotondati al multiplo più vicino di 10 alla potenza meno ndigits;" docs.python.org/3/library/functions.html#round quindi no, il round non sempre arrotonda, ad es.round(2.354, 2) # -> 2.35
Pete Kirkham,

@PeteKirkham hai ragione, ho modificato la mia risposta per avere più senso e precisione.
s4w3d0ff,

2
-0,54 è la risposta corretta per arrotondare -0,5357706 verso il basso perché è un numero negativo, -0,54 <-0,53
s4w3d0ff

2
Vorrei usare 10**dinvece di int('1' + ('0' * d)).
Jonathon Reinhart,

11
float(str(round(answer, 2)))
float(str(round(0.0556781255, 2)))

8

Vuoi arrotondare la tua risposta.

round(value,significantDigit)è la soluzione ordinaria per farlo, tuttavia a volte questo non funziona come ci si aspetterebbe da una prospettiva matematica quando la cifra immediatamente inferiore (a sinistra di) alla cifra che stai arrotondando ha un 5.

Ecco alcuni esempi di questo comportamento imprevedibile:

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

Supponendo che il tuo intento sia quello di fare il tradizionale arrotondamento per le statistiche nelle scienze, questo è un pratico wrapper per far roundfunzionare la funzione come previsto, necessitando di importcose extra come Decimal.

>>> round(0.075,2)

0.07

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

0.08

Aha! Quindi in base a questo possiamo fare una funzione ...

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

Fondamentalmente questo aggiunge un valore molto piccolo alla stringa per costringerlo ad arrotondare correttamente nelle istanze imprevedibili dove normalmente non ha la roundfunzione quando ci si aspetta. Un valore conveniente da aggiungere è 1e-Xdov'è Xla lunghezza della stringa numerica che stai cercando di usare roundsu più 1.

L'approccio dell'uso è 10**(-len(val)-1)stato deliberato, in quanto è il numero più piccolo che è possibile aggiungere per forzare lo spostamento, garantendo anche che il valore aggiunto non cambi mai l'arrotondamento anche se .manca il decimale . Potrei usare solo 10**(-len(val))con un condizionale if (val>1)per sottrarre di 1più ... ma è più semplice sottrarre sempre il 1dato che non cambierà molto l'intervallo applicabile di numeri decimali che questa soluzione alternativa può gestire correttamente. Questo approccio fallirà se i tuoi valori raggiungono i limiti del tipo, questo fallirà, ma per quasi l'intero intervallo di valori decimali validi dovrebbe funzionare.

Quindi il codice finito sarà simile a:

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

... dovrebbe darti i risultati che ti aspetti.

Puoi anche usare la libreria decimale per farlo, ma il wrapper che propongo è più semplice e può essere preferito in alcuni casi.


Modifica: Grazie Blckknght per aver sottolineato che il 5caso marginale si verifica solo per determinati valori qui .


6

Usa la formattazione con% .2f che ti dà arrotondamento per difetto a 2 decimali.

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

4

È possibile utilizzare l'operatore di formattazione delle stringhe di Python "%". "% .2f" significa 2 cifre dopo il punto decimale.

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


4

È possibile utilizzare l' operatore round per un massimo di 2 decimali

num = round(343.5544, 2)
print(num) // output is 343.55

3

È possibile utilizzare la funzione rotonda.

round(80.23456, 3)

ti darà una risposta di 80.234

Nel tuo caso, usa

answer = str(round(answer, 2))

Spero che questo ti aiuti :)


2

Se è necessario evitare problemi in virgola mobile sull'arrotondamento dei numeri per la contabilità, è possibile utilizzare il giro intorpidito.

È necessario installare numpy:

pip install numpy

e il codice:

import numpy as np

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

stampe

2.67
2.68

Dovresti usarlo se gestisci denaro con arrotondamenti legali.


1

Ecco un esempio che ho usato:

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)

1

Non so perché, ma il formato "{: 0.2f}" (0,5357706) mi dà "0,54". L'unica soluzione che funziona per me (python 3.6) è la seguente:

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

Questo è troncare, non arrotondare.
ShadowRanger


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.