Wynik obliczeń ma za dużo miejsc po przecinku, a w raporcie potrzebujesz dwóch: zwykle wystarczy round(wynik, 2), ale rezultat może zaskoczyć, jeśli liczba jest typu float. Szczególnie mylące bywa round(2.675, 2), które zwraca 2.67, choć spodziewany wynik to często 2.68.

Najkrócej o zaokrąglaniu liczb w Pythonie
- Składnia:
round(liczba, ndigits)zaokrągla do wskazanej liczby miejsc po przecinku. - Remisy: wbudowane
round()wybiera bliższą parzystą wartość, gdy liczba leży dokładnie pośrodku. - Precyzja:
floatprzechowuje liczby dziesiętne jako przybliżenia binarne, co może wpływać na wynik. - Pieniądze: do kontrolowanego zaokrąglania wartości dziesiętnych użyj
Decimali jawnie ustaw tryb. - Wyświetlanie: f-string z formatem
.2fpokazuje dwa miejsca po przecinku, ale zwraca tekst.
round() przyjmuje liczbę i opcjonalną precyzję
Masz wynik 3.14159 i chcesz skrócić go do dwóch miejsc? Użyj drugiego argumentu funkcji: round(3.14159, 2) zwróci 3.14. Gdy pominiesz precyzję, Python zaokrągli do najbliższej liczby całkowitej.
round(3.14159) # 3
round(3.14159, 2) # 3.14
round(1234, -2) # 1200
Argument ndigits może być dodatni, równy zeru lub ujemny. Ujemna wartość zaokrągla do dziesiątek, setek i kolejnych potęg dziesięciu, więc przydaje się choćby do skracania dużych wyników w podsumowaniach. Dokumentacja funkcji wbudowanych Pythona opisuje też, że bez podanego ndigits wynikiem jest liczba całkowita, a z nim zwracany jest typ zgodny z typem argumentu.
Przy remisie Python wybiera parzysty wynik
Zaokrąglanie nie zawsze oznacza „piątka w górę”. Wbudowane round() stosuje regułę ties to even: jeśli wartość znajduje się dokładnie w połowie między dwiema możliwościami, wybiera parzystą.
round(2.5) # 2
round(3.5) # 4
round(1.25, 1) # 1.2
round(1.35, 1) # 1.4
Przy wielu obliczeniach taka reguła ogranicza systematyczne przesuwanie wyników w jedną stronę. Jeśli jednak specyfikacja wymaga zaokrąglania połówek od zera, domyślny wynik może nie pasować. Uważam, że właśnie tę różnicę najlepiej sprawdzić przed wyborem metody zaokrąglania, zamiast zakładać, że każda funkcja realizuje szkolną regułę.
Wynik 2.67 dla 2.675 wynika z reprezentacji float
Przykład round(2.675, 2) często wygląda jak błąd funkcji. Przyczyną jest zapis liczby typu float: większości ułamków dziesiętnych nie da się dokładnie przedstawić w systemie binarnym, więc program operuje na najbliższym możliwym przybliżeniu. W tym przypadku wartość przechowywana przez Pythona znajduje się nieco poniżej dziesiętnego 2.675.
round(2.675, 2) # 2.67
To nie znaczy, że round() ignoruje liczbę miejsc po przecinku. Zaokrągla otrzymaną wartość binarną zgodnie ze swoją regułą. Wyjaśnienie tej pułapki oraz ograniczeń arytmetyki zmiennoprzecinkowej podaje samouczek Pythona o liczbach zmiennoprzecinkowych.
Decimal pozwala jawnie wybrać regułę dla wartości dziesiętnych
Gdy liczy się dziesiętna wartość wejściowa, a nie jej binarne przybliżenie, użyj Decimal. Przekaż liczbę jako tekst: Decimal("2.675") zachowa zapis dziesiętny, podczas gdy przekazanie wcześniej utworzonego float przeniosłoby jego niedokładność do nowego obiektu.
from decimal import Decimal, ROUND_HALF_UP
kwota = Decimal("2.675")
wynik = kwota.quantize(
Decimal("0.01"),
rounding=ROUND_HALF_UP
)
print(wynik) # 2.68
ROUND_HALF_UP zaokrągla remisy od zera, a więc zachowuje się inaczej niż domyślny remis do parzystej wbudowanego round(). Moduł decimal udostępnia też inne tryby, między innymi ROUND_HALF_EVEN oraz ROUND_DOWN. Dokumentacja modułu decimal opisuje metodę quantize(), która ustala wykładnik wyniku, na przykład dwa miejsca po przecinku.
F-string ustawia wygląd wyniku, a nie jego typ liczbowy
Jeśli wynik ma trafić do tabeli, raportu lub komunikatu, często nie potrzebujesz zmieniać wartości liczbowej. Zapis f"{liczba:.2f}" formatuje ją jako tekst z dokładnie dwoma cyframi po przecinku.
cena = 8.5
print(f"{cena:.2f}") # 8.50
To przydatne, gdy chcesz zachować końcowe zero, którego liczba typu float sama z siebie nie przechowuje jako elementu zapisu. Pamiętaj jednak, że wynikiem formatowania jest str, nie liczba gotowa do dalszych obliczeń; składnię formatu opisuje dokumentacja formatowanych napisów Pythona.
Dobierz metodę do tego, co robisz z wynikiem
Ta sama liczba może wymagać innego podejścia zależnie od tego, czy dalej ją liczysz, czy tylko pokazujesz. Tabela pomaga uniknąć częstej pomyłki: potraktowania formatu tekstowego jak precyzyjnego zaokrąglenia wartości.
| Sytuacja | Prawdopodobna przyczyna lub skutek | Co zrobić |
|---|---|---|
round(2.675, 2) daje 2.67 |
float przechowuje przybliżenie binarne |
Jeśli potrzebujesz dziesiętnej reguły, użyj Decimal("2.675") |
Po round(8.5, 2) widzisz 8.5, a chcesz 8.50 |
Liczba nie przechowuje informacji o końcowym zerze | Wyświetl ją przez f"{liczba:.2f}" |
| Wartość połówkowa zaokrągla się w nieoczekiwaną stronę | round() rozstrzyga dokładny remis na korzyść parzystego wyniku |
Wybierz Decimal i określ wymagany tryb zaokrąglania |
| Zaokrąglona wartość ma być dalej używana w obliczeniach | Formatowanie f-stringiem daje tekst | Użyj round() albo Decimal.quantize(), stosownie do wymagań |
Najpierw ustal, czy zaokrąglasz wartość, czy jej zapis
Do zwykłych obliczeń i typowych wartości float wybierz round(liczba, ndigits). Gdy potrzebujesz określonej reguły dla wartości dziesiętnych, użyj Decimal; gdy chodzi wyłącznie o czytelny zapis, formatuj wynik f-stringiem. Najpierw określ oczekiwany rezultat, potem dobierz narzędzie, bo dwa miejsca po przecinku mogą oznaczać precyzję liczby albo tylko wygląd tekstu.
