round(value,significantDigit)
è la soluzione ordinaria, tuttavia questo non funziona come ci si aspetterebbe da un punto di vista matematico, quando arrotondare i valori che terminano in 5
. Se il numero 5
è nella cifra subito dopo quella a cui si è arrotondato, a volte questi valori vengono arrotondati come previsto (ad esempio arrotondando a due cifre decimali l'8.005
corrisponde a 8.01
). Per alcuni valori dovuti ai capricci della matematica in virgola mobile, vengono invece arrotondati per difetto!
cioè
>>> 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
strano.
Supponendo che il vostro intento è quello di fare l'arrotondamento tradizionale per le statistiche nel campo delle scienze, questo è un wrapper a portata di mano per ottenere la funzione round
funziona come previsto la necessità di import
roba extra come Decimal
.
>>> round(0.075,2)
0.07
>>> round(0.075+10**(-2*5),2)
0.08
Aha! Quindi, sulla base di questo siamo in grado di fare una funzione di ...
def roundTraditional(val,digits):
return round(val+10**(-len(str(val))-1))
Fondamentalmente questo aggiunge un valore garantito di essere più piccolo del minimo data cifra della stringa che stai cercando di utilizzare round
su. Aggiungendo questa piccola quantità il comportamento di round
nella maggior parte dei casi è preservato, mentre ora si assicura se la cifra inferiore a quella arrotondata a è 5
che arrotonda, e se è 4
si arrotonda.
L'approccio dell'utilizzo di 10**(-len(val)-1)
è stato intenzionale, in quanto è il numero più piccolo che è possibile aggiungere per forzare lo spostamento, garantendo inoltre che il valore aggiunto non cambierà mai l'arrotondamento anche se manca il decimale .
. Potrei usare solo 10**(-len(val))
con un if (val>1)
condizionale per sottrarre 1
di più ... ma è più semplice sottrarre sempre il valore 1
in quanto ciò non cambierà molto l'intervallo applicabile di numeri decimali che questa soluzione 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.
È anche possibile utilizzare la libreria decimal per eseguire questa operazione, ma il wrapper che propongo è più semplice e può essere preferito in alcuni casi.
Edit: Grazie Blckknght per aver ricordato che il caso 5
frangia si verifica solo per certi valori. Anche una versione precedente di questa risposta non era sufficientemente esplicita che il comportamento di arrotondamento dispari si verifica solo quando la cifra immediatamente inferiore alla cifra a cui si sta arrotondando ha un 5
.
vorrei provare 'int (x)' –