Menu

Klasa Math w Javie: pow, sqrt, abs, round, random i inne

Jak używać klasy Math w Javie: Math.pow, Math.sqrt, Math.abs, Math.max i Math.min, zaokrąglanie przez round, floor i ceil, losowanie liczby z zakresu przez Math.random oraz stałe PI i E, razem z typem zwracanym przez każdą metodę.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Skrzynka z narzędziami: metody statyczne

java.lang.Math to klasa pełna gotowych funkcji matematycznych: potęgi, pierwiastki, wartości bezwzględne, zaokrąglanie, trygonometria, logarytmy i liczby losowe. Dwie rzeczy sprawiają, że łatwo jej używać:

  • Znajduje się w java.lang, który każdy plik Javy importuje automatycznie. Nie trzeba pisać żadnej linii import.
  • Każda metoda jest static. Wywołujesz ją na nazwie klasy, Math.sqrt(25), i nigdy nie tworzysz obiektu Math. Strona o składowych statycznych wyjaśnia, co oznacza static.

Zwróć uwagę, że niektóre wyniki są wypisywane z .0, a inne nie. Każda metoda Math ma stały typ zwracany i jego znajomość to większość tego, czego trzeba się nauczyć o tej klasie.

MetodaCo robiZwraca
Math.pow(a, b)a do potęgi bdouble
Math.sqrt(x)pierwiastek kwadratowydouble
Math.cbrt(x)pierwiastek sześciennydouble
Math.abs(x)wartość bezwzględnaten sam typ co x
Math.max(a, b) / Math.min(a, b)większa / mniejsza z dwóchszerszy z dwóch typów
Math.round(x)najbliższa liczba całkowitalong dla double, int dla float
Math.floor(x) / Math.ceil(x)zaokrąglenie w dół / w górędouble
Math.random()liczba losowa od 0.0 do 1.0double
Math.PI, Math.Estałe π i edouble

Math.pow: potęgi

Math.pow(base, exponent) podnosi liczbę do potęgi. Przyjmuje dwa parametry double i zwraca double, nawet gdy przekazujesz liczby całkowite:

Aby zapisać wynik w int, zrzutuj go przez (int). Dla małych potęg całkowitych wynik double jest dokładny, więc rzutowanie daje poprawną odpowiedź. Problem pojawia się przy dużych wynikach: double większy niż Integer.MAX_VALUE (2 147 483 647) po rzutowaniu daje dokładnie Integer.MAX_VALUE, więc (int) Math.pow(2, 40) daje 2147483647. Przy większych potęgach rzutuj na long i pamiętaj, że powyżej 2⁵³ double nie potrafi dokładnie przedstawić każdej liczby całkowitej. Strona o rzutowaniu typów opisuje, co rzutowanie robi z wartością.

Java nie ma operatora potęgowania. 2 ^ 3 się kompiluje, ale ^ to bitowy XOR, a wynik to 1, nie 8. To jeden z najczęstszych błędów początkujących w kodzie matematycznym w Javie.

double równy dziesięć milionów lub więcej wypisuje się w notacji naukowej, co zaskakuje przy pierwszym wypisaniu potęgi dziesięciu:

1.0E7 oznacza 1.0 × 10⁷. Wartość jest ta sama, zmienia się tylko sposób wypisania. Aby wypisać ją jako zwykłe cyfry, zrzutuj ją na long albo sformatuj przez String.format("%.0f", value).

Math.sqrt i Math.cbrt: pierwiastki

Math.sqrt(x) zwraca pierwiastek kwadratowy z x jako double. Math.cbrt(x) zwraca pierwiastek sześcienny.

Pierwiastek kwadratowy z liczby ujemnej nie jest liczbą rzeczywistą, więc Math.sqrt(-4) zwraca NaN ("not a number", czyli "nie liczba") zamiast rzucać wyjątek. NaN rozprzestrzenia się na każde działanie, którego dotknie, więc jeśli możliwe są wartości ujemne, sprawdzaj dane przed liczeniem pierwiastka. Math.hypot(a, b) liczy bezpośrednio sqrt(a*a + b*b), co jest popularnym sposobem na odległość między dwoma punktami.

Math.abs: wartość bezwzględna

Math.abs(x) usuwa znak. W odróżnieniu od pow i sqrt zwraca ten sam typ, który dostaje: int dla int, double dla double.

Typowe zastosowanie to różnica, w której liczy się wielkość, a nie kierunek, np. odległość między dwiema pozycjami.

Math.max i Math.min

Math.max(a, b) zwraca większą z dwóch wartości, a Math.min(a, b) mniejszą. Przyjmują dokładnie dwa argumenty. Dla trzech lub więcej zagnieżdżaj wywołania:

Gdy dwa argumenty mają różne typy, węższy jest najpierw rozszerzany. Math.max(3, 7.5) porównuje dwie wartości double i zwraca double. Ostatni przykład ogranicza wartość do zakresu od 0 do 100: Math.min przycina ją do 100, a Math.max nie pozwala jej spaść poniżej 0.

Zaokrąglanie: round, floor, ceil

Java ma trzy metody zaokrąglania i różnią się zarówno kierunkiem, jak i typem zwracanym:

  • Math.round zaokrągla do najbliższej liczby całkowitej. Wartość dokładnie w połowie zaokrągla się w górę, w stronę plus nieskończoności, więc 2.5 daje 3, a -2.5 daje -2. Dla argumentu double zwraca long (a dla float zwraca int).
  • Math.floor zawsze zaokrągla w dół, w stronę minus nieskończoności, i zwraca double.
  • Math.ceil zawsze zaokrągla w górę, w stronę plus nieskończoności, i zwraca double.
  • Rzutowanie (int) w ogóle nie jest zaokrąglaniem: odcina część ułamkową, co przesuwa liczby dodatnie w dół, a ujemne w górę.

Ponieważ Math.round(double) zwraca long, przypisanie wyniku do int bez rzutowania się nie kompiluje:

int n = Math.round(2.6);          // error: incompatible types: possible lossy conversion from long to int
int m = (int) Math.round(2.6);    // OK, m wynosi 3
long k = Math.round(2.6);         // OK

Aby zaokrąglić do określonej liczby miejsc po przecinku, pomnóż, zaokrąglij i podziel z powrotem. Dzielenie przez 100.0 (double) zamiast przez 100 zachowuje część dziesiętną:

Druga linia dzieli long przez int, czyli wykonuje dzielenie całkowite, więc część dziesiętna przepada. Jeśli zaokrągloną liczbę trzeba tylko wyświetlić, String.format("%.2f", value) jest prostsze i nie zmienia przechowywanej wartości.

Math.random: liczby losowe

Math.random() zwraca double, który jest co najmniej 0.0 i mniejszy niż 1.0. Przy każdym wywołaniu wartość jest inna, więc wynik programów w tej sekcji zmienia się po każdym kliknięciu Run.

Aby dostać liczbę całkowitą z zakresu, rozciągnij tę wartość, zrzutuj ją i przesuń. Dla liczby całkowitej od min do max, oba końce włącznie:

int value = (int) (Math.random() * (max - min + 1)) + min;

Tak to działa dla kostki, gdzie min to 1, a max to 6:

  1. Math.random() * 6 daje double od 0.0 do 6.0, bez samego 6.0.
  2. (int) odcina część ułamkową, co daje jedną z wartości 0, 1, 2, 3, 4, 5.
  3. + 1 przesuwa ją do 1, 2, 3, 4, 5, 6.

Pierwsza linia pokazuje pięć losowych rzutów. Druga sprawdza dziesięć tysięcy rzutów i w praktyce zawsze wypisuje lowest: 1, highest: 6: wzór dochodzi do obu końców zakresu i nigdy ich nie przekracza.

Nawiasy wokół Math.random() * (max - min + 1) mają znaczenie. Rzutowanie dotyczy wartości tuż po nim, więc (int) Math.random() * 6 najpierw rzutuje Math.random(). To zawsze daje 0, a 0 * 6 to 0, więc każdy "rzut" wychodzi taki sam.

Math.random() wystarcza do gier i ćwiczeń. W innych przypadkach klasa java.util.Random i ThreadLocalRandom.current().nextInt(min, max + 1) (w java.util.concurrent) zwracają liczby całkowite bezpośrednio, a Random może przyjąć ziarno (seed), aby w testach powtarzać tę samą sekwencję. Żadna z nich nie nadaje się do haseł ani tokenów bezpieczeństwa; do tego służy java.security.SecureRandom.

Math.PI i Math.E

Math.PI (π) i Math.E (liczba Eulera e) to stałe static final double:

Używaj ich zamiast wpisywać 3.14. Są tak dokładne, jak pozwala double, a nazwa mówi czytelnikowi, czym jest liczba.

Wyniki całkowite a wyniki double

Większość metod Math przyjmuje i zwraca double. Gdy podajesz im wartości int, Java automatycznie rozszerza argumenty do double, ale działania zapisane przed wywołaniem nadal wykonują się na int. Stąd bierze się większość błędnych wyników:

items / perBox to 7 / 2, a dzielenie dwóch wartości int odrzuca resztę, więc wynik to 3, zanim Math.ceil w ogóle go zobaczy. Math.ceil(3.0) to 3.0. Zamień jeden z operandów na double, rzutowaniem albo literałem takim jak 4.0, aby dzielenie zachowało część ułamkową. Strona o operatorach wyjaśnia dokładniej dzielenie całkowite.

Ogólna zasada: zdecyduj, jaki typ chcesz mieć na końcu, wykonuj dzielenie lub mnożenie na double, gdy liczą się ułamki, i rzutuj z powrotem na int albo long tylko raz, na samym końcu.

Inne przydatne metody

Kilka kolejnych metod z tej samej klasy, wywoływanych w ten sam sposób:

  • Math.log to logarytm naturalny; Math.log10 to logarytm dziesiętny.
  • Math.floorMod(a, b) daje resztę ze znakiem b, czyli to, czego potrzebujesz przy zawijaniu w obrębie zakresu, np. dni tygodnia. Operator % zachowuje znak a.
  • Metody trygonometryczne (sin, cos, tan) przyjmują radiany. Stopnie najpierw zamień przez Math.toRadians.
  • Math.addExact, Math.multiplyExact i pokrewne rzucają ArithmeticException przy przepełnieniu, zamiast po cichu przeskoczyć do liczby ujemnej.

Najczęściej zadawane pytania

Jak używać Math.pow w Javie?

Math.pow(base, exponent) zwraca base podniesione do potęgi exponent jako double, więc Math.pow(2, 3) to 8.0. Aby zapisać wynik w int, zrzutuj go: int n = (int) Math.pow(2, 10); daje 1024. Java nie ma operatora potęgowania ^; ^ to bitowy XOR.

Jak wylosować liczbę z zakresu za pomocą Math.random?

Math.random() zwraca double od 0.0 do 1.0, bez samego 1.0. Aby dostać liczbę całkowitą od min do max włącznie, użyj (int) (Math.random() * (max - min + 1)) + min. Rzut kostką to (int) (Math.random() * 6) + 1.

Czy trzeba importować klasę Math w Javie?

Nie. Math należy do pakietu java.lang, który każdy plik Javy importuje automatycznie. Wszystkie jej metody są static, więc wywołujesz je na nazwie klasy, np. Math.sqrt(16), bez tworzenia obiektu.

Dlaczego Math.round zwraca long w Javie?

Math.round(double) zwraca long, bo double może przechowywać wartości dużo większe niż int. Przypisanie wyniku do int wymaga rzutowania: int n = (int) Math.round(2.6);. Math.round(float) zwraca int.

Czym różnią się Math.floor, Math.ceil i Math.round?

Math.floor zaokrągla w dół (2.7 daje 2.0, -2.3 daje -3.0), Math.ceil zaokrągla w górę (2.1 daje 3.0), a Math.round do najbliższej liczby całkowitej, przy czym połówki idą w górę (2.5 daje 3). floor i ceil zwracają double; round zwraca long.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ