Opdeling efter nul i Java: Undtagelse, uendelig eller ikke et tal

1. Oversigt

At dividere med nul er en operation, der ikke har nogen betydning i almindelig aritmetik og derfor er udefineret. I programmering, dog mens det er ofte forbundet med en fejl, dette er ikke altid tilfældet.

I denne artikel gennemgår vi det hvad sker der, når en division med nul opstår i et Java-program.

I henhold til Java-specifikationen for delingsoperationen kan vi identificere to forskellige tilfælde af division med nul: heltal og flydende tal.

2. Heltal

For det første er det for heltal ret ret ligetil. At dele et heltal med nul vil resultere i et Aritmetisk undtagelse:

assertThrows (ArithmeticException.class, () -> {int result = 12/0;});
assertThrows (ArithmeticException.class, () -> {int result = 0/0;});

3. Typer af flydende punkt

Men når man handler med flydende tal, en undtagelse vil ikke blive kastet:

assertDoesNotThrow (() -> {float result = 12f / 0;});

For at håndtere sager som disse bruger Java nogle specielle numeriske værdier, der kan repræsentere resultaterne af en sådan operation: NaN, POSITIVE_INFINITYog NEGATIVE_INFINITY.

3.1. NaN

Lad os starte med dividere nulværdier med flydende punkt med nul:

assertEquals (Float.NaN, 0f / 0); assertEquals (Double.NaN, 0d / 0);

Resultatet i disse tilfælde er NaN (ikke et tal).

3.2. Uendelighed

Lad os derefter divider nogle værdier, der ikke er nul, med nul:

assertEquals (Float.POSITIVE_INFINITY, 12f / 0); assertEquals (Double.POSITIVE_INFINITY, 12d / 0); assertEquals (Float.NEGATIVE_INFINITY, -12f / 0); assertEquals (Double.NEGATIVE_INFINITY, -12d / 0);

Som vi kan se, er resultatet UENDELIGHED, med tegnet afhængigt af operandernes tegn.

Desuden kan vi også bruge begrebet negativt nul for at komme til NEGATIVE_INFINITY:

assertEquals (Float.NEGATIVE_INFINITY, 12f / -0f); assertEquals (Double.NEGATIVE_INFINITY, 12f / -0f);

3.3. Hukommelsesrepræsentation

Så hvorfor kaster heltal division med nul en undtagelse, mens flydende division med nul ikke gør det?

Lad os se på dette fra et hukommelsesrepræsentationsperspektiv. For heltal er der intet bitmønster, der kan bruges til at gemme resultatet af en sådan operation, mens flydende tal har værdier som NaN eller UENDELIGHED skal bruges i tilfælde som disse.

Lad os nu overveje den binære repræsentation af en float som S EEEEEEE E FFFFFFF FFFFFFFF FFFFFFFF med en bit (S) for tegnet, 8 bits (E) for eksponenten, og resten (F) for mantissen.

I hver af de tre værdier NaN, POSITIVE_INFINITY, og NEGATIVE_INFINITY, alle bits i eksponentdelen er indstillet til 1.

UENDELIGHED har mantissabitene alle indstillet til 0, mens NaN har en ikke-nul mantissa:

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. Resume

For at opsummere ting så vi i denne artikel, hvordan division med nul fungerer i Java.

Værdier som UENDELIGHED og NaN er tilgængelige for flydende tal, men ikke for heltal. Hvis du deler et heltal med nul, resulterer det i en undtagelse. Dog for en flyde eller dobbelt, Java tillader operationen.

Den komplette kode er tilgængelig på GitHub.