Arytmetyka liczb całkowitych i przepełnienie
Poznaj dzielenie całkowitoliczbowe, modulo, działanie przepełnienia oraz sposoby jego wykrywania.
Arytmetyka liczb całkowitych i przepełnienie to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Arytmetyka liczb całkowitych i przepełnienie
Liczby całkowite w Javie mają stały rozmiar. Gdy obliczenie przekroczy wartość maksymalną lub minimalną, następuje ciche zawinięcie zakresu — nie jest zgłaszany żaden wyjątek. Zrozumienie tego mechanizmu pomaga zapobiegać trudnym do wykrycia błędom.
Zakresy liczb całkowitych
Każdy typ całkowity ma ograniczony zakres określony przez szerokość bitową:
byte: od -128 do 127short: od -32 768 do 32 767int: od -2 147 483 648 do 2 147 483 647long: od -9.2 × 10^18 do 9.2 × 10^18
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Integer.MIN_VALUE); // -2147483648
System.out.println(Long.MAX_VALUE); // 9223372036854775807
System.out.println(Byte.MAX_VALUE); // 127Przepełnienie: ciche zawijanie zakresu
Dodanie 1 do Integer.MAX_VALUE powoduje zawinięcie wartości do Integer.MIN_VALUE. Jest to arytmetyka w kodzie uzupełnień do dwóch — Java nie daje żadnej gwarancji i nie zgłasza żadnego wyjątku.
int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 (overflow!)
byte b = 127;
b++; // wraps to -128
System.out.println(b); // -128
// Real bug: counting votes in a large election with int
int votes = Integer.MAX_VALUE;
votes += 100; // silently wrong
System.out.println(votes); // negative number!Wykrywanie przepełnienia za pomocą Math.addExact
Java 8+ wprowadziła Math.addExact(), multiplyExact() i subtractExact(), które w przypadku przepełnienia zgłaszają ArithmeticException zamiast cicho zawijać wartość.
try {
int result = Math.addExact(Integer.MAX_VALUE, 1);
} catch (ArithmeticException e) {
System.out.println("Overflow detected!"); // prints this
}
try {
long safe = Math.multiplyExact(100_000L, 100_000L);
System.out.println(safe); // 10000000000
} catch (ArithmeticException e) {
System.out.println("Multiply overflow");
}Dzielenie całkowite i modulo
Dzielenie całkowite obcina część ułamkową w kierunku zera. Operator % zwraca resztę z dzielenia ze znakiem dzielnej. Należy uważać na dzielenie przez zero — powoduje ono zgłoszenie ArithmeticException.
System.out.println(10 / 3); // 3 (not 3.33)
System.out.println(10 % 3); // 1
System.out.println(-10 % 3); // -1 (sign follows dividend)
System.out.println(-10 % -3); // -1
try {
int x = 5 / 0; // ArithmeticException: / by zero
} catch (ArithmeticException e) {
System.out.println(e.getMessage()); // / by zero
}
// Float division by zero gives Infinity, not exception
System.out.println(5.0 / 0); // InfinityArytmetyka long dla dużych liczb
Należy używać typu long, gdy wartości mogą przekroczyć zakres typu int. Zawsze należy dodawać L do literałów typu long, aby zapobiec przepełnieniu przed przypisaniem wartości.
// Bug: multiplication done as int, then widened
long wrong = 1_000_000 * 1_000_000; // overflows int!
System.out.println(wrong); // -727379968 (wrong!)
// Fix: one operand is long
long correct = 1_000_000L * 1_000_000L;
System.out.println(correct); // 1000000000000
// Or cast first
long alsOk = (long) 1_000_000 * 1_000_000;
System.out.println(alsOk); // 1000000000000Operatory przesunięcia bitowego
Operatory przesunięcia bitowego to szybkie sposoby mnożenia i dzielenia przez potęgi liczby 2:
n << k— przesunięcie w lewo: mnożenie przez 2^kn >> k— arytmetyczne przesunięcie w prawo: dzielenie przez 2^kn >>> k— przesunięcie w prawo bez znaku: uzupełnianie zerami
int n = 8;
System.out.println(n << 1); // 16 (8 * 2)
System.out.println(n << 2); // 32 (8 * 4)
System.out.println(n >> 1); // 4 (8 / 2)
System.out.println(n >> 2); // 2 (8 / 4)
// Check if number is power of 2
boolean isPow2 = n > 0 && (n & (n - 1)) == 0;
System.out.println(isPow2); // trueBitowe AND, OR i XOR
Operatory bitowe działają na pojedynczych bitach i są używane w uprawnieniach, flagach oraz protokołach niskopoziomowych.
int a = 0b1010; // 10
int b = 0b1100; // 12
System.out.println(Integer.toBinaryString(a & b)); // 1000 (AND = 8)
System.out.println(Integer.toBinaryString(a | b)); // 1110 (OR = 14)
System.out.println(Integer.toBinaryString(a ^ b)); // 0110 (XOR = 6)
System.out.println(Integer.toBinaryString(~a)); // ...11110101 (NOT)
// Permission flags example
int READ = 0b001;
int WRITE = 0b010;
int EXEC = 0b100;
int perms = READ | WRITE; // user has read+write
System.out.println((perms & EXEC) != 0); // false — no execPodkreślenia w literałach liczbowych
Java 7+ pozwala używać podkreśleń w literałach liczbowych, aby poprawić ich czytelność. Kompilator je ignoruje.
int million = 1_000_000;
long creditCard = 4_111_1111_1111_1111L;
double pi = 3.141_592_653_589_793;
int hex = 0xFF_EC_D1_2E;
int binary = 0b0001_0101_0110;
System.out.println(million); // 1000000
System.out.println(creditCard); // 4111111111111111BigInteger dla dowolnej precyzji
Gdy wartości przekraczają zakres typu long, należy użyć BigInteger. Nie występuje w nim przepełnienie, ale jest wolniejszy od typów prymitywnych. Używaj go do kluczy kryptograficznych, silni i liczb astronomicznych.
import java.math.BigInteger;
BigInteger factorial100 = BigInteger.ONE;
for (int i = 2; i <= 100; i++) {
factorial100 = factorial100.multiply(BigInteger.valueOf(i));
}
System.out.println(factorial100.toString().length() + " digits"); // 158 digits
BigInteger a = new BigInteger("999999999999999999999999999999");
BigInteger b = new BigInteger("1");
System.out.println(a.add(b)); // 1000000000000000000000000000000Praktyka: licznik odporny na przepełnienie
Wzorzec implementowania licznika, który bezpiecznie obsługuje przepełnienie, korzystając z Math.addExact i w razie potrzeby przechodząc na Long.MAX_VALUE.
class SafeCounter {
private long count = 0;
public void increment() {
try {
count = Math.addExact(count, 1L);
} catch (ArithmeticException e) {
count = Long.MAX_VALUE; // cap at max
}
}
public long get() { return count; }
}
SafeCounter sc = new SafeCounter();
sc.increment();
sc.increment();
System.out.println(sc.get()); // 2Szybkie sprawdzenie
Jaka jest wartość poniższego wyrażenia?
long result = 1_000_000 * 1_000_000; System.out.println(result);
Podsumowanie: arytmetyka całkowita i przepełnienie
Najważniejsze informacje:
- Przepełnienie liczb całkowitych powoduje ciche zawijanie wartości — domyślnie nie jest zgłaszany wyjątek
- Używaj Math.addExact/multiplyExact/subtractExact, aby wykrywać przepełnienie
- Dzielenie całkowite obcina wynik w kierunku zera; znak operatora % jest zgodny ze znakiem dzielnej
- Używaj literałów typu long (sufiks L), gdy wyniki pośrednie mogą spowodować przepełnienie typu int
- BigInteger obsługuje dowolnie duże wartości bez przepełnienia
- Operatory przesunięcia bitowego są szybką alternatywą dla mnożenia i dzielenia przez potęgę dwójki
Często zadawane pytania
Czy lekcja „Arytmetyka liczb całkowitych i przepełnienie” jest bezpłatna?
Tak — pełny tekst „Arytmetyka liczb całkowitych i przepełnienie” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Arytmetyka liczb całkowitych i przepełnienie”?
Poznaj dzielenie całkowitoliczbowe, modulo, działanie przepełnienia oraz sposoby jego wykrywania. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Arytmetyka liczb całkowitych i przepełnienie”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Najważniejsze elementy klasy Math
- Arytmetyka liczb całkowitych i przepełnienie
- BigDecimal w obliczeniach finansowych
- NumberFormat i printf