Typ pierwotny | Rozmiar w pamięci | Zakres wartości |
---|---|---|
bajt | 8 bitowy | -128 do 127 |
krótki | 16 bitów | -32768 do 32767 |
zwęglać | 16 bitów | od 0 do 65536 |
int | 32 bity | -2147483648 do 2147483647 |
długi | 64-bitowy | -9223372036854775808 do 9223372036854775807 |
platforma | 32 bity | (2 do potęgi -149) do ((2 do potęgi -23) * 2 do potęgi 127) |
podwójnie | 64-bitowy | (-2 do potęgi 63) do ((2 do potęgi 63) - 1) |
logiczna | 8 (gdy jest używany w tablicach), 32 (gdy nie jest używany w tablicach) | prawda czy fałsz |
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
System.out.println(decimal);
}
}
Przekazanie ciągu do konstruktora to tylko jedna z możliwych opcji. Tutaj używamy ciągów znaków, ponieważ nasze liczby przekraczają maksymalne wartości dla long i double , i potrzebujemy jakiegoś sposobu, aby wyjaśnić kompilatorowi, którą liczbę chcemy utworzyć :) 11111111111111111111111111111111111111111111111111111111111111111111111111 do konstruktora nie zadziała: Java spróbuje wcisnąć przekazaną liczbę do jednego z prymitywnych typów danych, ale nie będzie pasować do żadnego z nich. Dlatego dobrym rozwiązaniem jest użycie ciągu znaków do przekazania żądanej liczby. Obie klasy mogą automatycznie wyodrębniać wartości liczbowe z przekazanych ciągów znaków. Inną ważną kwestią, o której należy pamiętać podczas pracy z klasami o dużej liczbie, jest to, że ich obiekty są niezmienne ( Immutable ). Niezmienność jest Ci już znana dzięki doświadczeniu z klasą String i klasami opakowującymi dla typów pierwotnych (Integer, Long itp.).
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
integer.add(BigInteger.valueOf(33333333));
System.out.println(integer);
}
}
Wyjście konsoli:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Jak można się spodziewać, nasz numer się nie zmienił. Aby wykonać operację dodawania, musisz utworzyć nowy obiekt, aby otrzymać wynik operacji.
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
System.out.println(integer);
BigInteger result = integer.add(BigInteger.valueOf(33333333));
System.out.println(result);
}
}
Wyjście konsoli:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Widzisz, teraz wszystko działa tak, jak powinno :) Swoją drogą, czy zauważyłeś, jak nietypowo wygląda operacja dodawania?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
To kolejny ważny punkt. Klasy z dużymi liczbami nie używają operatorów + - * /. Zamiast tego udostępniają zestaw metod. Zapoznajmy się z głównymi (jak zwykle pełną listę metod znajdziecie w dokumentacji Oracle: tutaj i tutaj ).
-
metody operacji arytmetycznych: add() , subtract() , mnożenie() , dzielenie() . Metody te służą odpowiednio do dodawania, odejmowania, mnożenia i dzielenia.
-
doubleValue() , intValue() , floatValue() , longValue() itd. służą do konwersji dużej liczby na jeden z prymitywnych typów Javy. Zachowaj ostrożność podczas korzystania z tych metod. Nie zapomnij o różnicach w wielkości bitów!
import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); long result = integer.longValue(); System.out.println(result); } }
Wyjście konsoli:
8198552921648689607
-
min() i max() pozwalają znaleźć minimalną i maksymalną wartość dwóch dużych liczb.
Pamiętaj, że te metody nie są statyczne!import java.math.BigInteger; public class Main { public static void main(String[] args) { BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"); BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222"); System.out.println(integer.max(integer2)); } }
Wyjście konsoli:
222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
Zachowanie zaokrąglania BigDecimal
Ten temat ma oddzielną sekcję, ponieważ zaokrąglanie dużych liczb i konfigurowanie zachowania zaokrąglania nie jest takie proste. Możesz użyć metody setScale() , aby ustawić liczbę miejsc dziesiętnych dla BigDecimal . Załóżmy na przykład, że chcemy, aby liczba 111,5555555555 miała trzy cyfry po przecinku. Nie możemy jednak osiągnąć tego, czego chcemy, przekazując liczbę 3 jako argument do metody setScale() . Jak wspomniano powyżej, BigDecimalsłuży do reprezentowania liczb z surowymi wymaganiami dotyczącymi precyzji obliczeniowej. W obecnej formie nasz numer ma 10 cyfr po przecinku. Chcemy zrzucić 7 z nich i zachować tylko 3. W związku z tym oprócz liczby 3 musimy przejść tryb zaokrąglania. BigDecimal ma łącznie 8 trybów zaokrąglania. To dużo! Ale jeśli naprawdę potrzebujesz dostroić precyzję swoich obliczeń, będziesz miał wszystko, czego potrzebujesz. Oto 8 trybów zaokrąglania oferowanych przez BigDecimal :-
ROUND_CEILING — zaokrągla w górę
111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
-
ROUND_DOWN — zaokrągla do zera
111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
-
ROUND_FLOOR — zaokrągla w dół
111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
-
ROUND_HALF_UP — zaokrągla w górę, jeśli liczba po przecinku >= 0,5
0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
-
ROUND_HALF_DOWN — zaokrągla w górę, jeśli liczba po przecinku > 0,5
0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
-
ROUND_HALF_EVEN — zaokrąglenie zależy od liczby po lewej stronie przecinka dziesiętnego. Jeśli liczba po lewej stronie jest parzysta, zaokrąglenie będzie mniejsze. Jeśli liczba po lewej stronie przecinka dziesiętnego jest nieparzysta, zaokrąglenie zostanie wykonane w górę.
2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
Liczba po lewej stronie przecinka to 2 (parzyste). Liczba jest zaokrąglana w dół. Chcemy 0 miejsc po przecinku, więc wynikiem jest 2.
3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
Liczba po lewej stronie przecinka dziesiętnego to 3 (nieparzysta). Liczba jest zaokrąglana w górę. Chcemy 0 miejsc po przecinku, więc wynikiem jest 4.
-
ROUND_UNNECCESSARY — Ten tryb jest używany, gdy musisz przekazać metodzie tryb zaokrąglania, ale liczba nie musi być zaokrąglana. Jeśli spróbujesz zaokrąglić liczbę z ustawionym trybem ROUND_UNNECCESSARY, zostanie zgłoszony wyjątek ArithmeticException.
3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
-
ROUND_UP — zaokrągla od zera.
111.5551 -> setScale(3, ROUND_UP) -> 111.556
Porównywanie dużych liczb
To też jest ważne. Pamiętasz, że używamy metody equals() do porównywania obiektów w Javie. Implementacja jest dostarczana przez sam język (dla standardowych klas Java) lub nadpisywana przez programistę. Ale w przypadku obiektów BigDecimal nie zaleca się używania metody equals() do porównań. Dzieje się tak, ponieważ metoda BigDecimal.equals() zwraca wartość true tylko wtedy, gdy dwie liczby mają tę samą wartość i skalę: Porównajmy zachowanie metody equals() dla klas Double i BigDecimal :import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
Double a = 1.5;
Double b = 1.50;
System.out.println(a.equals(b));
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.equals(y));
}
}
Wyjście konsoli:
true
false
Jak widać, dla BigDecimal liczby 1.5 i 1.50 okazały się nierówne! Wynikało to właśnie ze specyfiki implementacji metody equals() w klasie BigDecimal . Aby uzyskać dokładniejsze porównanie dwóch obiektów BigDecimal , lepiej jest użyć metody CompareTo() :
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
BigDecimal x = new BigDecimal("1.5");
BigDecimal y = new BigDecimal("1.50");
System.out.println(x.compareTo(y));
}
}
Wyjście konsoli:
0
Metoda CompareTo () zwróciła 0, co oznacza, że 1,5 i 1,50 są równe. I takiego wyniku oczekiwaliśmy! :) To kończy naszą dzisiejszą lekcję. Teraz czas wrócić do zadań! :)