ArithmeticException în Java

Apare la o operație aritmetică imposibilă: împărțirea unui întreg la zero, depășiri cu Math.addExact, BigDecimal fără rotunjire.

Sintaxă
public class ArithmeticException extends RuntimeException

Ce face ArithmeticException

Cel mai des, ArithmeticException apare la împărțirea a doi întregi (int, long) la zero, cu / sau %; mesajul este / by zero. La double împărțirea la zero nu aruncă excepție: dă Infinity sau NaN.

O aruncă și metodele „exacte” din Math (addExact, multiplyExact, toIntExact) când rezultatul nu încape în tip, precum și BigDecimal.divide când rezultatul are zecimale infinite și nu ai dat rotunjirea.

Ce returnează

Excepția este aruncată de operație; o poți prinde cu catch (ArithmeticException e).

Exemple

Exemplul 1: Media unei clase fără elevi

public class Main {
    static int medie(int[] note) {
        int s = 0;
        for (int n : note) s += n;
        return s / note.length;
    }

    public static void main(String[] args) {
        System.out.println("Media: " + medie(new int[] {8, 9, 10}));
        try {
            System.out.println("Media: " + medie(new int[] {}));
        } catch (ArithmeticException e) {
            System.out.println("Eroare: " + e.getMessage());
        }
        double zero = 0;
        System.out.println("La double: 5 / 0.0 = " + (5 / zero) + ", 0 / 0.0 = " + (0 / zero));
    }
}

Rezultat

Media: 9
Eroare: / by zero
La double: 5 / 0.0 = Infinity, 0 / 0.0 = NaN

Exemplul 2: Depășire detectată cu Math.multiplyExact

public class Main {
    public static void main(String[] args) {
        int pret = 50_000;
        int bucati = 60_000;
        System.out.println("Fără verificare: " + (pret * bucati));
        try {
            System.out.println(Math.multiplyExact(pret, bucati));
        } catch (ArithmeticException e) {
            System.out.println("multiplyExact: " + e.getMessage());
        }
        System.out.println("Cu long: " + Math.multiplyExact((long) pret, bucati));
    }
}

Rezultat

Fără verificare: -1294967296
multiplyExact: integer overflow
Cu long: 3000000000

Exemplul 3: BigDecimal fără rotunjire

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
    public static void main(String[] args) {
        BigDecimal suma = new BigDecimal("10");
        BigDecimal persoane = new BigDecimal("3");
        try {
            suma.divide(persoane);
        } catch (ArithmeticException e) {
            System.out.println(e.getMessage());
        }
        System.out.println("Cu rotunjire: " + suma.divide(persoane, 2, RoundingMode.HALF_UP));
    }
}

Rezultat

Non-terminating decimal expansion; no exact representable decimal result.
Cu rotunjire: 3.33

Greșeli frecvente

  • Nu verifici împărțitorul când vine din date (număr de elevi, de zile). Verifică if (n == 0) înainte.
  • Te aștepți la excepție la double. 1.0 / 0 dă Infinity; verifică cu Double.isFinite.

Comenzi înrudite

  • BigDecimal.divide: Împărțire între BigDecimal; când rezultatul are zecimale infinite (10/3) trebuie să dai scala și modul de rotunjire.
  • RuntimeException: Clasa de bază a excepțiilor neverificate: nu trebuie declarate cu throws și nici prinse obligatoriu.
  • Math.addExact: Adunare, scădere, înmulțire, incrementare și negare care aruncă ArithmeticException la overflow în loc să dea rezultat greșit.