web-dev-qa-db-fra.com

Comment détecter un débordement d'entier sur un entier 32 bits?

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?

29
ashur

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);
}
34
Patryk Czarnik
long test = (long)x+y;
if (test > Integer.MAX_VALUE || test < Integer.MIN_VALUE)
   // Overflow!
13
Tim B

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

8
Vusal

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;
}
3
Durandal

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 longs n'est pas moins efficace que travailler avec ints (l'inverse peut être vrai). Donc, si vous avez le choix entre vérifier les débordements ou utiliser longs, optez pour ce dernier.

1
GOTO 0