MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Modulul decimal

Atunci când lucrăm cu numere în virgulă mobilă (adică float), ne putem confrunta cu situația în care rezultatul calculelor nu este complet corect:

number = 0.1 + 0.1 + 0.1
print(number)       # 0.30000000000000004

Această problemă poate fi rezolvată folosind funcția round(), care va rotunji numărul. Cu toate acestea, există o altă soluție, care constă în utilizarea modulului integrat decimal.

Componenta cheie pentru lucrul cu numere în acest modul este clasa Decimal. Pentru a o folosi, trebuie să creăm un obiect al acestei clase cu ajutorul constructorului. În constructor se transmite o valoare sub formă de șir de caractere, care reprezintă numărul:

from decimal import Decimal

number = Decimal("0.1")

După aceea, obiectul Decimal poate fi utilizat în operațiuni aritmetice:

from decimal import Decimal

number = Decimal("0.1")
number = number + number + number
print(number)       # 0.3

În operațiunile cu Decimal, putem folosi numere întregi:

number = Decimal("0.1")
number = number + 2

Totuși, nu putem amesteca în operațiuni numere în virgulă mobilă float și Decimal:

number = Decimal("0.1")
number = number + 0.1   # aici va apărea o eroare

Cu ajutorul zecimalelor suplimentare, putem defini câte caractere vor fi în partea zecimală a numărului:

number = Decimal("0.10")
number = 3 * number
print(number)       # 0.30

Șirul "0.10" definește două zecimale, chiar dacă ultimele caractere sunt zerouri. În mod corespunzător, "0.100" reprezintă trei zecimale.

Rotunjirea numerelor

Obiectele Decimal au metoda quantize(), care permite rotunjirea numerelor. În această metodă, ca prim argument, se transmite și un obiect Decimal care indică formatul de rotunjire a numărului:

from decimal import Decimal

number = Decimal("0.444")
number = number.quantize(Decimal("1.00"))
print(number)       # 0.44

number = Decimal("0.555678")
print(number.quantize(Decimal("1.00")))       # 0.56

number = Decimal("0.999")
print(number.quantize(Decimal("1.00")))       # 1.00

Șirul "1.00" indică faptul că rotunjirea va fi până la două zecimale.

Implicit, rotunjirea este descrisă de constanta ROUND_HALF_EVEN, unde rotunjirea se face la cel mai apropiat număr par dacă partea de rotunjire este 5. De exemplu:

from decimal import Decimal, ROUND_HALF_EVEN

number = Decimal("10.025")      # 2 - cel mai apropiat număr par
print(number.quantize(Decimal("1.00"), ROUND_HALF_EVEN))       # 10.02

number = Decimal("10.035")      # 4 - cel mai apropiat număr par
print(number.quantize(Decimal("1.00"), ROUND_HALF_EVEN))       # 10.04

Strategia de rotunjire este transmisă ca al doilea parametru în quantize.

Șirul "1.00" înseamnă că rotunjirea va fi până la două zecimale. În primul caz, "10.025" - a doua zecimală este 2 - un număr par, așa că, deși următorul număr este 5, doi nu se rotunjește la trei.

În al doilea caz, "10.035" - a doua zecimală este 3 - un număr impar, iar cel mai apropiat număr par va fi 4, astfel încât 35 se rotunjește la 40.

Acest comportament la rotunjire poate să nu fie dorit de toată lumea, și în acest caz poate fi redefinit, folosind una dintre următoarele constante:

  • ROUND_HALF_UP: rotunjește numărul în sus dacă după el urmează numărul 5 sau mai mare
  • ROUND_HALF_DOWN: rotunjește numărul în jos dacă după el urmează un număr mai mare de 5
number = Decimal("10.026")
print(number.quantize(Decimal("1.00"), ROUND_HALF_DOWN))       # 10.03

number = Decimal("10.025")
print(number.quantize(Decimal("1.00"), ROUND_HALF_DOWN))       # 10.02
  • ROUND_05UP: rotunjește 0 la 1 dacă după el urmează numărul 5 sau mai mare
number = Decimal("10.005")
print(number.quantize(Decimal("1.00"), ROUND_05UP))       # 10.01

number = Decimal("10.025")
print(number.quantize(Decimal("1.00"), ROUND_05UP))       # 10.02
  • ROUND_CEILING: rotunjește numărul în sus indiferent de numărul care urmează după el
number = Decimal("10.021")
print(number.quantize(Decimal("1.00"), ROUND_CEILING))       # 10.03

number = Decimal("10.025")
print(number.quantize(Decimal("1.00"), ROUND_CEILING))       # 10.03
  • ROUND_FLOOR: nu rotunjește numărul indiferent de numărul care urmează după el
number = Decimal("10.021")
print(number.quantize(Decimal("1.00"), ROUND_FLOOR))       # 10.02

number = Decimal("10.025")
print(number.quantize(Decimal("1.00"), ROUND_FLOOR))       # 10.02
← Lecția anterioară Lecția următoare →