1. Wprowadzenie
W życiu codziennym rzadko potrzebujemy widzieć długie „ogonki” po przecinku. Na przykład, gdy liczysz cenę towaru, pensję, średnią ocenę albo powierzchnię pokoju — zwykle wystarczą dwa miejsca po przecinku, a nie 15.
Na przykład, wynik dzielenia:
double x = 10.0 / 3.0;
System.out.println(x); // 3.3333333333333335
Użytkownik, widząc taki wynik, może się przestraszyć i pomyśleć, że program zwariował. Dlatego liczby często trzeba zaokrąglać — do najbliższej liczby całkowitej, do dwóch miejsc po przecinku i tak dalej.
W Javie jest do tego kilka wygodnych narzędzi.
2. Metoda Math.round(): zaokrąglanie do najbliższej liczby całkowitej
Najprostszy sposób zaokrąglenia liczby — skorzystać z metody Math.round(). Przyjmuje liczbę zmiennoprzecinkową (zarówno float, jak i double) i zwraca najbliższą liczbę całkowitą.
Jak działa Math.round
- Jeśli część ułamkowa jest mniejsza niż 0.5 — zaokrągla w dół.
- Jeśli część ułamkowa wynosi 0.5 lub więcej — zaokrągla w górę.
Przykłady:
System.out.println(Math.round(2.3)); // 2
System.out.println(Math.round(2.7)); // 3
System.out.println(Math.round(2.5)); // 3
System.out.println(Math.round(-2.5)); // -2
Typ zwracanej wartości
- Jeśli przekażesz float, zwróci int.
- Jeśli przekażesz double, zwróci long.
float f = 5.8f;
int roundedF = Math.round(f); // 6
double d = 5.8;
long roundedD = Math.round(d); // 6
Zwróć uwagę: to czasem zaskakuje — zaokrągliłeś double, a dostałeś long! Jeśli potrzebujesz int, musisz wykonać rzutowanie jawne:
int rounded = (int) Math.round(5.6); // 6
3. Zaokrąglanie do określonej liczby miejsc po przecinku
Często trzeba zaokrąglić nie do całkowitej, lecz np. do dwóch miejsc po przecinku (dla pieniędzy, procentów itp.).
W Javie nie ma „magicznej” metody w rodzaju Math.roundTo2Digits(), ale można to zrobić ręcznie.
Sposób 1: trik matematyczny z mnożeniem i dzieleniem
- Mnożymy liczbę przez 100 (jeśli potrzebne są dwa miejsca).
- Zaokrąglamy do całkowitej za pomocą Math.round.
- Dzielimy z powrotem przez 100.
Przykład:
double value = 3.14159;
double rounded = Math.round(value * 100.0) / 100.0;
System.out.println(rounded); // 3.14
Jak to działa:
- 3.14159 * 100 = 314.159
- Math.round(314.159) = 314
- 314 / 100.0 = 3.14
4. Formatowanie liczb: klasa DecimalFormat
Czasem trzeba nie tylko zaokrąglić liczbę, ale też ładnie ją wyświetlić — z określoną liczbą miejsc po przecinku, wiodącymi zerami, separatorami tysięcy itp. Do tego w Javie służy klasa DecimalFormat z pakietu java.text.
Jak działa DecimalFormat
- Tworzymy obiekt z odpowiednim wzorcem.
- Wywołujemy na nim metodę format(...).
import java.text.DecimalFormat;
double value = 3.14159;
DecimalFormat df = new DecimalFormat("0.00");
System.out.println(df.format(value)); // 3.14
Jak działa wzorzec
- "0.00" — zawsze dwa miejsca po przecinku (nawet jeśli liczba jest całkowita).
- "0.###" — do trzech miejsc po przecinku, zbędne zera nie są wyświetlane.
- "#,##0.00" — dodaje separatory tysięcy (na przykład "1,234.56").
Przykłady różnych wzorców:
| Wzorzec | Liczba | Wynik |
|---|---|---|
|
2 | 2.00 |
|
2.5 | 2.50 |
|
2.567 | 2.57 |
|
2.567 | 2.567 |
|
2.5 | 2.5 |
|
12345.678 | 12,345.68 |
Przykład z separatorami tysięcy
DecimalFormat df = new DecimalFormat("#,##0.00");
System.out.println(df.format(1234567.89)); // 1,234,567.89
Przykład: bez zbędnych zer
DecimalFormat df = new DecimalFormat("0.##");
System.out.println(df.format(3.1)); // 3.1
System.out.println(df.format(3.141)); // 3.14
System.out.println(df.format(3.145)); // 3.15
5. Formatowanie przy użyciu String.format
Czasem w prostych przypadkach wygodne jest użycie String.format — wbudowanego sposobu formatowania łańcuchów, podobnego do printf w innych językach.
double value = 3.14159;
System.out.println(String.format("%.2f", value)); // 3.14
Tutaj "%.2f" — oznacza „wyświetl liczbę z dwoma miejscami po przecinku”.
Porównanie podejść:
- DecimalFormat — potężniejszy, obsługuje wzorce i lokalizację, wygodny do separatorów tysięcy.
- String.format — prostszy, gdy trzeba tylko ustawić liczbę miejsc po przecinku.
6. Niuanse zaokrąglania: Math.floor, Math.ceil, Math.rint
- Math.floor(x) — zaokrągla w dół (w kierunku mniejszej wartości), także dla liczb ujemnych.
- Math.ceil(x) — zaokrągla w górę (w kierunku większej wartości).
- Math.rint(x) — zaokrągla do najbliższej całkowitej, ale zwraca double.
Przykłady:
System.out.println(Math.floor(2.7)); // 2.0
System.out.println(Math.ceil(2.1)); // 3.0
System.out.println(Math.rint(2.5)); // 2.0 (tak, tak — to nie literówka!)
System.out.println(Math.rint(3.5)); // 4.0
Uwaga: Math.rint czasem zaokrągla „do najbliższej parzystej” — ta zasada (tzw. banker's rounding) pomaga zmniejszać kumulację błędów przy masowych obliczeniach.
7. Przydatne niuanse
Wizualizacja: tabela zaokrągleń
| Liczba | Math.round | Math.floor | Math.ceil | Math.rint |
|---|---|---|---|---|
| 2.3 | 2 | 2.0 | 3.0 | 2.0 |
| 2.5 | 3 | 2.0 | 3.0 | 2.0 |
| 3.5 | 4 | 3.0 | 4.0 | 4.0 |
| -2.3 | -2 | -3.0 | -2.0 | -2.0 |
| -2.5 | -2 | -3.0 | -2.0 | -2.0 |
Zaokrąglanie to nie to samo co formatowanie!
Bardzo ważne jest zrozumienie różnicy między zaokrąglaniem a formatowaniem.
- Zaokrąglanie — zmiana wartości liczby (np. 2.718 → 2.72).
- Formatowanie — zmiana sposobu, w jaki liczba wygląda przy wyświetlaniu (np. 2.718 → "2.72" na ekranie, ale w pamięci pozostaje 2.718).
double x = 2.718;
System.out.println(String.format("%.2f", x)); // 2.72
System.out.println(x); // 2.718
Jeśli chcesz używać zaokrąglonej liczby w dalszych obliczeniach — zaokrąglaj matematycznie! Jeśli tylko do wyświetlania — formatuj.
8. Typowe błędy przy zaokrąglaniu i formatowaniu liczb
Błąd nr 1: Zaokrągliłeś tylko do wyświetlenia, a dalej używasz „długiej” liczby.
Bardzo częsta sytuacja — ładnie sformatować wartość na ekranie, a następnie użyć pierwotnej „długiej” liczby w obliczeniach. Dla pieniędzy, punktów i podsumowań — najpierw zaokrąglij (np. Math.round albo trik z mnożeniem/dzieleniem), potem zapisuj/przekazuj użytkownikowi.
Błąd nr 2: Oczekiwanie, że Math.round(x) zwróci double z dwoma miejscami po przecinku.
Math.round() zawsze zaokrągla do najbliższej liczby całkowitej: dla float zwraca int, dla double — long. Do dwóch miejsc użyj mnożenia/dzielenia lub formatowania.
Błąd nr 3: Używanie DecimalFormat do obliczeń.
DecimalFormat.format() zwraca łańcuch. Nie można go używać w arytmetyce: dostaniesz błąd kompilacji albo NumberFormatException przy ponownym parsowaniu.
Błąd nr 4: Nieprawidłowy wzorzec DecimalFormat.
Wzorzec musi odpowiadać oczekiwaniom: "0.00" zawsze pokaże dwa miejsca ("2.00"), a "0.##" usunie zbędne zera ("2", "2.1", "2.12").
Błąd nr 5: Utrata precyzji przy dzieleniu przez 100.
Jeśli dzielisz int przez int, wynik też będzie int!
int a = 5;
System.out.println(a / 2); // 2, a nie 2.5!
Aby dzielenie było „z ułamkiem”, co najmniej jeden operand powinien być typu double:
int a = 5;
System.out.println(a / 2.0); // 2.5
GO TO FULL VERSION