Je sais qu'un tel sujet a été posé plusieurs fois, mais ma question concerne le débordement sur 32 bits complets . Par exemple:
11111111111111111111111111111111 +
00000000000000000000000000000001 =
00000000000000000000000000000000 //overflow!
J'ai trouvé sujet avec une question similaire à ce sujet, mais l'algorithme n'est pas parfait.
11111111111111111111111111111111 +
00000000000000000000000000000000 =
00000000000000000000000000000000 //overflow!
Existe-t-il un moyen simple, rapide et plus sûr de vérifier cela?
Depuis Java 8, il existe un ensemble de méthodes dans la classe Math : toIntExact ( long), addExact (int, int), subtractExact (int, int), multiplyExact (int, int), et les versions aussi longtemps. Ils lèvent ArithmeticException si un débordement se produit, ils renvoient le résultat approprié s'il convient dans la gamme.
Exemple d'ajout:
int x = 2000000000;
int y = 1000000000;
try {
int result = Math.addExact(x, y);
System.out.println("The proper result is " + result);
} catch(ArithmeticException e) {
System.out.println("Sorry, " + e);
}
long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
// Overflow!
Essayez de cette façon:
boolean isOverflow(int left, int right) {
return right > 0
? Integer.MAX_VALUE - right < left
: Integer.MIN_VALUE - right > left;
}
De: https://wiki.sei.cmu.edu/confluence/display/Java/NUM00-J.+Detect+or+prevent+integer+overflow
Le débordement peut être détecté par une expression logique du bit le plus significatif des deux opérandes et le résultat (tronqué) (j'ai pris l'expression logique du manuel du MC68030):
/**
* Add two int's with overflow detection (r = s + d)
*/
public static int add(int s, int d) throws ArithmeticException {
int r = s + d;
if (((s & d & ~r) | (~s & ~d & r)) < 0)
throw new ArithmeticException("int overflow add(" + s + ", " + d + ")");
return r;
}
La méthode la plus intuitive à laquelle je peux penser: calculer la somme (ou la différence) en tant que long
, puis convertir cette somme en int
et voir si sa valeur a changé.
long longSum = (long) a + b;
int sum = (int) longSum;
if (sum == longSum) {
// sum contains the correct result
} else {
// overflow/underflow
}
N'oubliez pas que sur les processeurs 64 bits modernes, travailler avec long
s n'est pas moins efficace que travailler avec int
s (l'inverse peut être vrai). Donc, si vous avez le choix entre vérifier les débordements ou utiliser long
s, optez pour ce dernier.