Podjela nula u Javi: izuzetak, beskonačnost ili nije broj
1. Pregled
Dijeljenje s nulom je operacija koja nema značenja u uobičajenoj aritmetici i, prema tome, nije definirana. U programiranju, međutim, dok to je često povezan s pogreškom, to nije uvijek slučaj.
U ovom ćemo članku proći što se događa kad se dogodi dijeljenje s nulom u programu Java.
Prema Java specifikaciji operacije dijeljenja, možemo identificirati dva različita slučaja dijeljenja s nulom: cijeli brojevi i brojevi s pomičnom zarezom.
2. Cijeli brojevi
Prvo, kod cijelih brojeva stvari su prilično jednostavne. Dijeljenje cijelog broja s nulom rezultirat će znakom ArithmeticException:
assertThrows (ArithmeticException.class, () -> {int rezultat = 12/0;});
assertThrows (ArithmeticException.class, () -> {int rezultat = 0/0;});
3. Vrste s pomičnom zarezom
Međutim, kad se bave s brojevima s pomičnom zarezom, iznimka se neće izbaciti:
assertDoesNotThrow (() -> {rezultat s pomicanjem = 12f / 0;});
Kako bi riješila slučajeve poput ovih, Java koristi neke posebne numeričke vrijednosti koje mogu predstavljati rezultate takve operacije: NaN, POZITIVNA_BESKRAJNOST, i NEGATIVNA_BESKRAJNOST.
3.1. NaN
Krenimo od dijeljenje nula vrijednosti s pomičnim zarezom s nulom:
assertEquals (Float.NaN, 0f / 0); assertEquals (Double.NaN, 0d / 0);
Rezultat u tim slučajevima je NaN (nije broj).
3.2. Beskonačnost
Dalje, idemo podijeliti neke vrijednosti koje nisu nula s nulom:
assertEquals (Float.POSITIVE_INFINITY, 12f / 0); assertEquals (Double.POSITIVE_INFINITY, 12d / 0); assertEquals (Float.NEGATIVE_INFINITY, -12f / 0); assertEquals (Double.NEGATIVE_INFINITY, -12d / 0);
Kao što vidimo, rezultat je INFINITY, sa predznakom ovisno o predznaku operanda.
Štoviše, također možemo koristiti koncept negativne nule da bismo došli do NEGATIVNA_BESKRAJNOST:
assertEquals (Float.NEGATIVE_INFINITY, 12f / -0f); assertEquals (Double.NEGATIVE_INFINITY, 12f / -0f);
3.3. Predstavljanje memorije
Pa, zašto cjelobrojna podjela s nulom daje iznimku, dok podjela s pomičnom zarezom s nulom ne?
Pogledajmo ovo iz perspektive predstavljanja memorije. Za cijele brojeve ne postoji uzorak bitova koji se može koristiti za pohranu rezultata takve operacije, dok brojevi s pomičnom zarezom imaju vrijednosti poput NaN ili BESKONAČNOST da se koristi u ovakvim slučajevima.
Sada, razmotrimo binarni prikaz plovka kao S EEEEEEE E FFFFFFF FFFFFFFF FFFFFFFF s jednim bitom (S) za znak, 8 bitova (E) za eksponent, a ostatak (F) za mantisu.
U svakoj od tri vrijednosti NaN, POSITIVE_INFINITY, i NEGATIVE_INFINITY, svi bitovi u eksponentnom dijelu postavljeni su na 1.
BESKONAČNOST ima bitove mantise postavljene na 0, dok NaN ima manisu koja nije nula:
assertEquals (Float.POSITIVE_INFINITY, Float.intBitsToFloat (0b01111111100000000000000000000000)); assertEquals (Float.NEGATIVE_INFINITY, Float.intBitsToFloat (0b11111111100000000000000000000000)); assertEquals (Float.NaN, Float.intBitsToFloat (0b11111111100000010000000000000000)); assertEquals (Float.NaN, Float.intBitsToFloat (0b11111111100000011000000000100000));
4. Sažetak
Da sumiramo stvari, u ovom smo članku vidjeli kako podjela s nulom djeluje na Javi.
Vrijednosti poput BESKONAČNOST i NaN dostupni su za brojeve s pomičnom zarezom, ali ne i za cijele brojeve. Kao rezultat, dijeljenje cijelog broja s nulom rezultirat će iznimkom. Međutim, za plutati ili dvostruko, Java dopušta operaciju.
Kompletni kod dostupan je na GitHubu.