Vreau ca " a " să fie rotunjite pentru a 13.95.
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
A tur
funcția nu funcționează așa cum mă așteptam.
Se execută în ani cu numere în virgulă mobilă de faptul că nu toate numerele pot fi reprezentate exact. Linia de comandă este doar arată completă în virgulă mobilă formă de memorie.
Cu virgulă mobilă reprezentarea ta rotunjite versiune este același număr. Deoarece computerele sunt binare, ele stocheaza numere în virgulă mobilă ca un întreg și apoi împărțiți-l cu o putere de două astfel 13.95 va fi reprezentată într-un mod similar cu 125650429603636838/(2**53).
Dublă precizie numere de 53 de biți (16 cifre) de precizie și regulat plutește avea 24 de biți (8 cifre) de precizie. De virgulă mobilă tip în Python folosește dublă precizie pentru a stoca valori.
De exemplu,
>>> 125650429603636838/(2**53)
13.949999999999999
>>> 234042163/(2**24)
13.949999988079071
>>> a=13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a,2))
13.95
>>> print("{0:.2f}".format(a))
13.95
>>> print("{0:.2f}".format(round(a,2)))
13.95
>>> print("{0:.15f}".format(round(a,2)))
13.949999999999999
Dacă sunteți după numai două zecimale (pentru a afișa o valoare monetară, de exemplu), atunci aveți un cuplu de mai bine opțiuni:
Sunt nou format caietul de sarcini, String Specificația de Format Mini-Limbaj de:
Puteți face același lucru ca:
"{0:.2f}".format(13.949999999999999)
Notă ca mai sus returnează un șir de caractere. În scopul de a obține cât float, pur și simplu înfășurați cu float(...)`:
float("{0:.2f}".format(13.949999999999999))
Notă ca ambalaj cu float()` nu't schimba nimic:
>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{0:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
Built-in round()
lucreaza bine in Python 2.7 sau mai târziu.
Exemplu:
>>> round(14.22222223, 2)
14.22
Check out documentația.
Cele mai multe numere nu poate fi reprezentat exact în plutește. Dacă doriți pentru a rotunji numărul pentru că's ce formulă matematică sau algoritm necesită, apoi doriți să utilizați rotund. Dacă doriți doar pentru a restricționa afișarea la o anumită precizie, atunci nu't de a folosi chiar rotund și format ca acel șir. (Dacă doriți să-l afișeze cu o altă metodă de rotunjire, și acolo sunt tone, atunci ai nevoie pentru a amesteca cele două abordări.)
>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'
Și în cele din urmă, deși, probabil, cel mai important, dacă doriți exact matematica atunci nu't vreau plutește la toate. Exemplul de obicei se face cu bani și pentru a stoca 'de centi' ca un întreg.
Utilizarea
print"{:.2f}".format(a)
în loc de
print"{0:.2f}".format(a)
Pentru că acesta din urmă poate duce la ieșire erori atunci când încearcă să-ieșire de mai multe variabile (vezi comentarii).
Cu Python < 3 (de exemplu 2.6 sau 2.7), există două moduri de a face acest lucru.
# Option one
older_method_string = "%.9f" % numvar
# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)
Dar, rețineți că pentru Python versiunile de mai sus 3 (de exemplu, 3.2 sau 3.3), a doua opțiune este de preferat.
Pentru mai multe informații despre opțiunea a doua, îți sugerez acest link pe șir de formatare din Python documentația.
Și pentru mai multe informații despre opțiunea unu, acest link va fi suficient și are informații cu privire la diverse steaguri.
Rotunjirea problemă de intrare / ieșire a fost rezolvată definitiv de Python 2.7.0 și 3.1.
Corect rotunjite număr poate fi reversibil convertit înapoi și mai departe:
str -> float() -> repr() -> float () ... " sau " Zecimal -> float -> str -> Zecimal
Un tip Zecimal nu este necesar pentru stocare mai.
(Desigur, poate fi necesar pentru a completa un rezultat de adunare sau scădere de numere rotunjite pentru a elimina acumulate ultima erori de bit. O explicită Zecimal aritmetică poate fi mai la îndemână, dar o conversie șir de str()
(care este cu rotunjire la 12 cifre valabile) este destul de bun, de obicei, dacă nu o precizie extremă sau nu număr extrem de mare de succesive operații aritmetice este necesar.)
Infinit de testare:
import random
from decimal import Decimal
for x in iter(random.random, None): # Verify FOREVER that rounding is fixed :-)
assert float(repr(x)) == x # Reversible repr() conversion.
assert float(Decimal(repr(x))) == x
assert len(repr(round(x, 10))) <= 12 # Smart decimal places in repr() after round.
if x >= 0.1: # Implicit rounding to 12 significant digits
assert str(x) == repr(round(x, 12)) # by str() is good enough for small errors.
y = 1000 * x # Decimal type is excessive for shopping
assert str(y) == repr(round(y, 12 - 3)) # in a supermaket with Python 2.7+ :-)
Vezi note de Lansare Python 2.7 - Alte Modificări Lingvistice al patrulea paragraf:
Conversii între numere în virgulă mobilă și siruri de caractere sunt acum rotunjite în mod corect pe majoritatea platformelor. Aceste conversii au loc în mai multe locuri diferite: str() pe flotoare și numere complexe; float și complexe constructori; formatare numerică; serializarea și de-serializarea plutește și numere complexe, folosind
serif
,zeama
șijson
module; analiză a pluti și imaginar literali în cod Python; și Zecimale,-să-float de conversie.Legat de aceasta, repr() de un număr în virgulă mobilă x acum se întoarce un rezultat bazat pe mai scurt decimal string, care este garantat de a rotunji înapoi la x sub corectă rotunjire (cu tur-jumatate-pentru-chiar și modul de rotunjire). Anterior, acesta a dat un șir de caractere pe baza de rotunjire x 17 cifre zecimale.
Mai multe informații: formatarea "float" înainte de Python 2.7 fost similare la curent numpy.float64
. Ambele tipuri folosesc același 64 bit IEEE 754 dublă precizie, cu 52 de biți mantisa. O mare diferență este că np.float64.__repr__
este formatat în mod frecvent cu un exces de număr zecimal, astfel încât nu poate fi pierdut, dar nu valabile IEEE 754 număr există între 13.949999999999999 și 13.950000000000001. Rezultatul nu este frumos și de conversie repr(float(number_as_string))
nu este reversibilă cu numpy. Pe de altă parte: float.__repr__
este formatat astfel încât fiecare cifră este important; secvența este fără lacune și transformarea este reversibilă. Pur și simplu: Dacă tu, probabil, au un numpy.float64 număr, converti la normal plutesc în scopul de a fi formatat pentru oameni, nu pentru procesoare numerice, altfel nimic nu mai este necesar, cu Python 2.7+.
Puteți utiliza format operatorul de rotunjire valoarea de până la 2 zecimale în python:
print(format(14.4499923, '.2f')) // output is 14.45
Nimeni de aici nu pare să fi menționat-o încă, așa că permiteți-mi să dau un exemplu în Python 3.6's f-string/template-string format, care cred că este frumos îngrijite:
>>> f'{a:.2f}'
Aceasta funcționează bine cu mai multe exemple, cu operatorii și nu au nevoie de paranteze:
>>> print(f'Completed in {time.time() - start:.2f}s')
În Python 2.7:
a = 13.949999999999999
output = float("%0.2f"%a)
print output
Python tutorial are un apendice numit virgulă mobilă Aritmetică: Probleme și Limitări. Citit-o. Aceasta explică ceea ce se întâmplă și de ce Python este de a face cele mai bune. Ea are chiar și un exemplu care se potrivește cu a ta. Permiteți-mi să citez un pic:
0.1 0.10000000000000001
ai putea fi tentat să folosească rotunde()` funcția de a-l toaca înapoi la un singur cifre te-ai aștepta. Dar asta nu face nici diferența:
rotund(0.1, 1) 0.10000000000000001
problema este că binar valoarea în virgulă mobilă stocate pentru
"0.1"
era deja cel mai bun posibil binar apropierea de `1/10, așa că încearcă să rotund din nou nu se poate face mai bine: era deja la fel de bun ca acesta devine.o Altă consecință este că din
0.1
nu este exact 1/10, însumând zece valorile de 0.1
nu poate produce exact1.0
, fie:sum = 0.0 for i in range(10): ... suma += 0.1 ... suma 0.99999999999999989
O alternativă și o soluție la problemele tale ar fi utilizarea zecimal
modulul.
Ca @Matt a subliniat, Python 3.6 oferă f-siruri de caractere, și ei pot folosi, de asemenea, imbricate parametri:
value = 2.34558
precision = 2
width = 4
print(f'result: {value:{width}.{precision}f}')
care va afișa rezultat: 2.35
L's face exact ce ai spus asta de-a face și este de lucru corect. Cititi mai multe despre virgulă mobilă confuzie și poate încerca zecimal obiecte în loc.
Pentru fixarea în virgulă mobilă în tip dinamic limbi, cum ar fi Python, JavaScript, eu folosesc aceasta tehnica
# For example:
a = 70000
b = 0.14
c = a * b
print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980
Puteți folosi, de asemenea, Zecimale, după cum urmează:
from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')
getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
from decimal import Decimal
def round_float(v, ndigits=2, rt_str=False):
d = Decimal(v)
v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
if rt_str:
return v_str
return Decimal(v_str)
Rezultate:
Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'
Utilizați o combinație de Zecimale obiect și rotunde() metodă.
Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')