Ce face Math.addExact
Operațiile obișnuite cu int și long nu verifică depășirea: dacă rezultatul nu încape, se „întoarce” la capătul opus și programul continuă cu o valoare greșită. Metodele Exact fac aceleași calcule, dar aruncă ArithmeticException cu mesajul integer overflow (sau long overflow).
addExact(x, y) este x + y, subtractExact este x - y, multiplyExact este x * y, incrementExact(a) este a + 1, decrementExact(a) este a - 1, iar negateExact(a) este -a (overflow doar pentru MIN_VALUE). Folosește-le când lucrezi cu sume de bani, contoare sau dimensiuni, unde un rezultat greșit este mai rău decât o eroare.
Parametri
| Parametru | Descriere |
|---|---|
x, y |
Operanzii. |
a |
Pentru variantele cu un argument: valoarea de modificat. |
Ce returnează
Rezultatul exact, de tip int sau long.
Exemple
Exemplul 1: Overflow tăcut față de excepție
public class Main {
public static void main(String[] args) {
int sold = 2_000_000_000;
int depunere = 500_000_000;
System.out.println("Cu +: " + (sold + depunere));
try {
System.out.println(Math.addExact(sold, depunere));
} catch (ArithmeticException e) {
System.out.println("addExact: " + e.getMessage());
}
System.out.println(Math.addExact(1500L, 2500L));
}
}
Rezultat
Cu +: -1794967296
addExact: integer overflow
4000
Exemplul 2: Toate operațiile Exact
public class Main {
static void incearca(String nume, java.util.function.IntSupplier calcul) {
try {
System.out.println(nume + " = " + calcul.getAsInt());
} catch (ArithmeticException e) {
System.out.println(nume + ": " + e.getMessage());
}
}
public static void main(String[] args) {
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
incearca("subtractExact(100, 30)", () -> Math.subtractExact(100, 30));
incearca("subtractExact(min, 1)", () -> Math.subtractExact(min, 1));
incearca("multiplyExact(46341, 46341)", () -> Math.multiplyExact(46341, 46341));
incearca("incrementExact(41)", () -> Math.incrementExact(41));
incearca("incrementExact(max)", () -> Math.incrementExact(max));
incearca("decrementExact(min)", () -> Math.decrementExact(min));
incearca("negateExact(25)", () -> Math.negateExact(25));
incearca("negateExact(min)", () -> Math.negateExact(min));
}
}
Rezultat
subtractExact(100, 30) = 70
subtractExact(min, 1): integer overflow
multiplyExact(46341, 46341): integer overflow
incrementExact(41) = 42
incrementExact(max): integer overflow
decrementExact(min): integer overflow
negateExact(25) = -25
negateExact(min): integer overflow
Exemplul 3: Valoarea unei comenzi mari
Prețul este în bani (întreg); înmulțirea cu o cantitate mare poate depăși int.
public class Main {
static String total(int pretBani, int cantitate) {
try {
int bani = Math.multiplyExact(pretBani, cantitate);
return bani / 100 + " lei";
} catch (ArithmeticException e) {
return "comandă prea mare pentru int";
}
}
public static void main(String[] args) {
System.out.println(total(1250, 40));
System.out.println(total(1250, 2_000_000));
System.out.println(Math.multiplyExact(1250L, 2_000_000L) / 100 + " lei (cu long)");
}
}
Rezultat
500 lei
comandă prea mare pentru int
25000000 lei (cu long)
Greșeli frecvente
- Prinzi
ArithmeticExceptionși continui ca și cum nimic nu s-ar fi întâmplat. Excepția înseamnă că tipul ales este prea mic: treci lalongsau laBigInteger. - Folosești
addExactcudouble: metodele există doar pentruintșilong. Numereledoublenu dau overflow, ciInfinity.
Comenzi înrudite
Math.toIntExact: Transformă un long în int și aruncă ArithmeticException dacă valoarea nu încape, în loc să o taie în tăcere.Math.multiplyFull: multiplyFull înmulțește două int-uri cu rezultat long complet; multiplyHigh dă jumătatea de sus a produsului a două long-uri.Math.powExact: Putere și înmulțire întreagă exactă (Java 25): rezultat int/long sau ArithmeticException la overflow, inclusiv pentru numere fără semn.Integer: Clasa wrapper pentru int: obiectul care învelește un număr întreg, plus constante și metode de conversie.Math.floorDivExact: Variante ale împărțirii întregi care aruncă ArithmeticException la overflow, în loc să returneze un rezultat greșit.