Delenie nulou v Jave: Výnimka, Nekonečno alebo Nie číslo
1. Prehľad
Delenie nulou je operácia, ktorá nemá v bežnej aritmetike žiadny význam, a preto nie je definovaná. V programovaní však zatiaľ je často spojená s chybou, nie je to tak vždy.
V tomto článku si prejdeme čo sa stane, keď dôjde k deleniu nulou v programe Java.
Podľa špecifikácie Java operácie delenia môžeme identifikovať dva rôzne prípady delenia nulou: celé čísla a čísla s pohyblivou rádovou čiarkou.
2. Celé čísla
Po prvé, pri celých číslach sú veci celkom jednoduché. Vydelením celého čísla nulou bude mať za následok znak Aritmetická výnimka:
assertThrows (ArithmeticException.class, () -> {int vysledok = 12/0;});
assertThrows (ArithmeticException.class, () -> {int vysledok = 0/0;});
3. Typy s pohyblivou rádovou čiarkou
Pri jednaní však s číslami s pohyblivou rádovou čiarkou, výnimka nebude hodená:
assertDoesNotThrow (() -> {float result = 12f / 0;});
Na riešenie takýchto prípadov používa Java niektoré špeciálne číselné hodnoty, ktoré môžu predstavovať výsledky takejto operácie: NaN, POZITÍVNE_INFINITYa NEGATÍVNE_INFINITY.
3.1. NaN
Začnime tým delenie nulových hodnôt s pohyblivou rádovou čiarkou nulou:
assertEquals (Float.NaN, 0f / 0); assertEquals (Double.NaN, 0d / 0);
Výsledok v týchto prípadoch je NaN (nie číslo).
3.2. Nekonečno
Ďalej, poďme vydeliť niektoré nenulové hodnoty nulou:
assertEquals (Float.POSITIVE_INFINITY, 12f / 0); assertEquals (Double.POSITIVE_INFINITY, 12d / 0); assertEquals (Float.NEGATIVE_INFINITY, -12f / 0); assertEquals (Double.NEGATIVE_INFINITY, -12d / 0);
Ako vidíme, výsledok je INFINITY, znakom v závislosti od znaku operandov.
Okrem toho môžeme tiež použiť koncept zápornej nuly, aby sme sa dostali k NEGATÍVNE_INFINITY:
assertEquals (Float.NEGATIVE_INFINITY, 12f / -0f); assertEquals (Double.NEGATIVE_INFINITY, 12f / -0f);
3.3. Reprezentácia pamäte
Prečo teda delenie na celé číslo nulou vyvoláva výnimku, zatiaľ čo delenie s pohyblivou desatinnou čiarkou nulou nie?
Pozrime sa na to z pohľadu reprezentácie pamäte. Pre celé čísla neexistuje žiadny bitový vzor, ktorý by sa dal použiť na uloženie výsledku takejto operácie, zatiaľ čo čísla s pohyblivou rádovou čiarkou majú hodnoty ako NaN alebo NEKONEČNOSŤ sa má použiť v takýchto prípadoch.
Teraz uvažujme binárnu reprezentáciu plaváka ako S EEEEEEE E FFFFFFF FFFFFFFF FFFFFFFF s jedným bitom (S) pre znamienko, 8 bitmi (E) pre exponenta a zvyškom (F) pre mantisu.
V každej z troch hodnôt NaN, POZITÍVNE_INFINITY, a NEGATIVE_INFINITY, všetky bity v exponentovej časti sú nastavené na 1.
NEKONEČNOSŤ má bity mantisy všetky nastavené na 0, zatiaľ čo NaN má nenulovú mantisu:
assertEquals (Float.POSITIVE_INFINITY, Float.intBitsToFloat (0b01111111100000000000000000000000)); assertEquals (Float.NEGATIVE_INFINITY, Float.intBitsToFloat (0b11111111100000000000000000000000)); assertEquals (Float.NaN, Float.intBitsToFloat (0b111111111100000010000000000000000)); assertEquals (Float.NaN, Float.intBitsToFloat (0b11111111100000011000000000100000));
4. Zhrnutie
Aby sme to zhrnuli, v tomto článku sme videli, ako funguje delenie nulou v Jave.
Hodnoty ako NEKONEČNOSŤ a NaN sú k dispozícii pre čísla s pohyblivou rádovou čiarkou, ale nie pre celé čísla. Výsledkom je, že vydelenie celého čísla nulou spôsobí výnimku. Avšak pre a plavák alebo dvojitý, Java umožňuje túto operáciu.
Celý kód je k dispozícii na GitHub.