Typ prymitywny | Rozmiar w pamięci | Zakres wartości |
---|---|---|
bajt | 8 bitowy | -128 do 127 |
krótki | 16-bitowy | do -32768 do 32767 |
zwęglać | 16-bitowy | od 0 do 65536 |
wew | 32 bity | od -2147483648 do 2147483647 |
długi | 64 bity | od -9223372036854775808 do 9223372036854775807 |
platforma | 32 bity | od (2 do potęgi -149) do ((2-2 do potęgi -23)*2 do potęgi 127) |
podwójnie | 64 bity | od (-2 do potęgi 63) do ((2 do potęgi 63) - 1) |
wartość logiczna | 8 (w przypadku użycia w tablicach), 32 (w przypadku użycia w przypadku innych niż tablice) | prawda czy fałsz |
BigInteger
jest BigDecimal
praktycznie nieograniczona. Do czego służą te zajęcia? Przede wszystkim do obliczeń o niezwykle wysokich wymaganiach dotyczących dokładności. Istnieją np. programy, w których od dokładności obliczeń może zależeć ludzkie życie (oprogramowanie dla samolotów i rakiet czy dla sprzętu medycznego). Dlatego jeśli nawet 150. miejsce po przecinku odgrywa ważną rolę, BigDecimal
jest to najlepszy wybór. Poza tym dość często obiekty te wykorzystywane są w świecie finansów, gdzie niezwykle istotna jest także dokładność obliczeń co do najmniejszych wartości. Jak pracować z przedmiotami BigInteger
i BigDecimal
o czym warto o nich pamiętać? Obiekty tych klas tworzone są w następujący sposób:
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);
}
}
Przekazywanie ciągu jako parametru jest tylko jednym z możliwych konstruktorów. Here we use strings because our numbers exceed the maximum values long
and double
, and somehow we need to explain to the compiler exactly what number we want to get :) Just pass the number 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 to the constructor 1111111111111111111111111111111111111111111111111111111111111111111 will not work: Java will try to „dopasuj” przekazaną liczbę do jednego z prymitywnych typów danych, ale nie będzie ona pasować do żadnego z nich. Dlatego dobrym rozwiązaniem jest użycie ciągu znaków do przekazania żądanej liczby. Obie klasy potrafią 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
) . Zasadę niezmienności znasz już dobrze na przykładzie klasy String
i klas opakowujących dla prymitywów (Integer, Long i inne).
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:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
Nasze liczby nie zmieniły się, jak można się spodziewać. Aby operacja dodawania zakończyła się sukcesem należy utworzyć nowy obiekt i przypisać do niego wynik dodawania.
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:
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
Teraz wszystko działa jak należy :) 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 o dużych liczbach nie używają operatorów +-*/ w swoim działaniu, lecz zamiast tego udostępniają zestaw metod. Przyjrzyjmy się głównym z nich (pełną listę metod jak zawsze znajdziesz w dokumentacji Oracle: tutaj i tutaj ).
-
metody wykonywania operacji arytmetycznych:
add()
,subtract()
,multiply()
,divide()
. Używane odpowiednio do operacji dodawania, odejmowania, mnożenia i dzielenia. -
doubleValue()
,intValue()
,floatValue()
itplongValue()
. - Służy do konwersji dużej liczby na pierwotny typ Java. Zachowaj ostrożność podczas ich używania i pamiętaj o różnicy w pojemności!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()
imax()
- pozwalają znaleźć minimalną i maksymalną wartość dwóch przekazanych dużych liczb.
Uwaga: 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
Kontrola zaokrąglania BigDecimal
Temat ten poświęcono osobnemu rozdziałowi, ponieważ zaokrąglanie dużych liczb i ich korygowanie nie jest taką prostą rzeczą. Możesz ustawić liczbę miejsc dziesiętnych dla liczbyBigDecimal
za pomocą setScale()
. Przykładowo chcemy ustawić dokładność liczby 111,5555555555 na trzy miejsca po przecinku. Nie uda nam się jednak przekazać liczby 3 jako argumentu metody setScale()
i tym samym rozwiązać naszego problemu. Jak wspomniano powyżej, BigDecimal
są to liczby do obliczeń o zwiększonej dokładności. W obecnej formie nasza liczba ma 10 miejsc po przecinku. Chcemy odrzucić ich 7 i zostawić tylko 3. Dlatego oprócz liczby 3 musimy przekazać jako parametr tryb zaokrąglania . Łącznie dostępnych jest 8 trybów zaokrąglania BigDecimal
. Sporo! Ale jeśli chcesz naprawdę dostroić dokładność obliczeń w programie, będziesz mieć wszystko, czego potrzebujesz. Oto 8 trybów zaokrąglania dostępnych w BigDecimal
:
-
ROUND_CEILING
- zaokrąglać w górę111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
-
ROUND_DOWN
- usuwanie wydzieliny111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
-
ROUND_FLOOR
- zaokrąglenie w dół111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
-
ROUND_HALF_UP
— zaokrąglenie w górę, jeżeli liczba po przecinku >= 0,50.55 -> setScale(1, ROUND_HALF_UP) -> 0.6 0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
-
ROUND_HALF_DOWN
— zaokrąglenie w górę, jeżeli liczba po przecinku > 0,50.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5 0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
-
ROUND_HALF_EVEN
— zaokrąglenie będzie zależne od liczby znajdującej się po lewej stronie przecinka dziesiętnego. Jeżeli liczba po lewej stronie jest parzysta, wówczas zaokrąglenie zostanie wykonane w dół. Jeśli liczba po lewej stronie przecinka dziesiętnego jest nieparzysta, zostanie zaokrąglona w górę.2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
Liczba po lewej stronie przecinka dziesiętnego – 2 – jest parzysta. Zaokrąglanie następuje w dół. Ponieważ wymagamy 0 miejsc po przecinku, wynikiem będzie 2.
3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
Liczba po lewej stronie przecinka dziesiętnego – 3 – jest nieparzysta. Zaokrąglenie następuje w górę. Ponieważ wymagamy 0 miejsc po przecinku, wynikiem będzie 4.
-
ROUND_UNNECCESSARY
— stosowane w przypadkach, gdy trzeba przekazać tryb zaokrąglania do jakiejś metody, ale liczba nie musi być zaokrąglana. Jeśli spróbujesz zaokrąglić liczbę, gdy ustawiony jest tryb ROUND_UNNECCESSARY, zostanie zgłoszony wyjątek ArithmeticException.3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
-
ROUND_UP
- zaokrąglać w górę.111.5551 -> setScale(3, ROUND_UP) -> 111.556
Porównanie dużych liczb
To pytanie jest również ważne. Pamiętasz już, że metoda ta służy do porównywania obiektów w Javieequals()
. Jest albo dostarczany przez sam język (w przypadku klas wbudowanych w Javie), albo jest zastępowany przez programistę. Jednak w przypadku obiektów klas nie zaleca się BigDecimal
stosowania tej metody equals()
do porównania. Dzieje się tak dlatego, że BigDecimal.equals()
metoda dwuliczbowa zwraca wartość true tylko wtedy, gdy obie liczby mają tę samą wartość i skalę : Porównajmy zachowanie metod equals()
y Double
i y 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ć liczby 1,5 i 1,50 w przypadku c BigDecimal
okazały się nierówne! Stało się tak właśnie ze względu na specyfikę metody equals()
w klasie BigDecimal
. Aby uzyskać dokładniejsze porównanie obu, BigDecimal
lepiej zastosować metodę 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 równe 1,5 i 1,50. Na taki wynik liczyliśmy! :) Na tym kończymy naszą dzisiejszą lekcję. Czas wrócić do zadań! :)
GO TO FULL VERSION