web-dev-qa-db-fra.com

Que se passe-t-il lorsque vous incrémentez un entier au-delà de sa valeur maximale?

En Java, que se passe-t-il lorsque vous incrémentez un int (ou un octet/court/long) au-delà de sa valeur maximale? Est-ce que cela tourne à la valeur négative maximale?

Est-ce que AtomicInteger.getAndIncrement() se comporte aussi de la même manière?

47
Lyke

Dans la section Spécification du langage Java sur les opérations sur les entiers :

Les opérateurs entiers intégrés ne le font pas indiquer un débordement ou un débordement dans n’importe quel façon.

Les résultats sont spécifiés par la langue et sont indépendants de la version de la machine virtuelle Java: Integer.MAX_VALUE + 1 == Integer.MIN_VALUE et Integer.MIN_VALUE - 1 == Integer.MAX_VALUE. Il en va de même pour les autres types d'entiers.

Les objets entiers atomiques (AtomicInteger, AtomicLong, etc.) utilisent les opérateurs entiers normaux en interne, donc getAndDecrement(), etc.

61
Ted Hopp

Si vous faites quelque chose comme ça:

int x = 2147483647;
x++;

Si vous imprimez maintenant x, il aura la valeur -2147483648.

9
jterrace

Comme le dit jterrace, l'exécution Java "encapsulera" le résultat dans Integer.MIN_VALUE de -2147483648.

Mais cela est mathématiquement incorrect!!. La bonne réponse mathématique est 2147483648 . Mais un 'int' ne peut pas avoir une valeur de 2147483648 . Les limites 'int' sont -2147483648 à 2147483647

Alors, pourquoi Java ne lance-t-il pas une exception? Bonne question! Un objet de tableau serait.

Mais les auteurs de langage connaissent l'étendue de leurs types primitifs, ils utilisent donc la technique du "wrapping" pour éviter une exception coûteuse.

En tant que développeur, vous devez tester ces limites de type. Un simple test d’incrémentation serait:

if(x++ == Integer.MIN_VALUE)
   //boundary exceeded

Un test simple pour décrémenter serait

if(x-- == Integer.MAX_VALUE)
   //boundary exceeded

Un test complet pour les deux serait

if(x++ == Integer.MIN_VALUE || x-- == Integer.MAX_VALUE)
   //boundary exceeded
5
GregJF

Ce qui se passe est qu'un bit supplémentaire est ajouté au bit le plus à droite et que l'ordre est décrémenté comme un entier signé négativement ... Remarquez ce qui se passe après 'int_32'; 

    int _0  = 0b0000000000000000000000000000000;
    int _1  = 0b0000000000000000000000000000001;
    int _2  = 0b0000000000000000000000000000010;
    int _3  = 0b0000000000000000000000000000100;
    int _4  = 0b0000000000000000000000000001000;
    int _5  = 0b0000000000000000000000000010000;
    int _6  = 0b0000000000000000000000000100000;
    int _7  = 0b0000000000000000000000001000000;
    int _8  = 0b0000000000000000000000010000000;
    int _9  = 0b0000000000000000000000100000000;
    int _10 = 0b0000000000000000000001000000000;
    int _11 = 0b0000000000000000000010000000000;
    int _12 = 0b0000000000000000000100000000000;
    int _13 = 0b0000000000000000001000000000000;
    int _14 = 0b0000000000000000010000000000000;
    int _15 = 0b0000000000000000100000000000000;
    int _16 = 0b0000000000000001000000000000000;
    int _17 = 0b0000000000000010000000000000000;
    int _18 = 0b0000000000000100000000000000000;
    int _19 = 0b0000000000001000000000000000000;
    int _20 = 0b0000000000010000000000000000000;
    int _21 = 0b0000000000100000000000000000000;
    int _22 = 0b0000000001000000000000000000000;
    int _23 = 0b0000000010000000000000000000000;
    int _24 = 0b0000000100000000000000000000000;
    int _25 = 0b0000001000000000000000000000000;
    int _26 = 0b0000010000000000000000000000000;
    int _27 = 0b0000100000000000000000000000000;
    int _28 = 0b0001000000000000000000000000000;
    int _29 = 0b0010000000000000000000000000000;
    int _30 = 0b0100000000000000000000000000000;
    int _31 = 0b1000000000000000000000000000000;
    int _32 = 0b1111111111111111111111111111111;
    int _XX = 0b10000000000000000000000000000000; // numeric overflow.
    int _33 = 0b10000000000000000000000000000001;
    int _34 = 0b11000000000000000000000000000000;
    int _35 = 0b11100000000000000000000000000000;
    int _36 = 0b11110000000000000000000000000000;
    int _37 = 0b11111000000000000000000000000000;
    int _38 = 0b11111100000000000000000000000000;
    int _39 = 0b11111110000000000000000000000000;
    int _40 = 0b11111111000000000000000000000000;
    int _41 = 0b11111111100000000000000000000000;
    int _42 = 0b11111111110000000000000000000000;
    int _43 = 0b11111111111000000000000000000000;
    int _44 = 0b11111111111100000000000000000000;
    int _45 = 0b11111111111110000000000000000000;
    int _46 = 0b11111111111111000000000000000000;
    int _47 = 0b11111111111111100000000000000000;
    int _48 = 0b11111111111111110000000000000000;
    int _49 = 0b11111111111111111000000000000000;
    int _50 = 0b11111111111111111100000000000000;
    int _51 = 0b11111111111111111110000000000000;
    int _52 = 0b11111111111111111111000000000000;
    int _53 = 0b11111111111111111111100000000000;
    int _54 = 0b11111111111111111111110000000000;
    int _55 = 0b11111111111111111111111000000000;
    int _56 = 0b11111111111111111111111100000000;
    int _57 = 0b11111111111111111111111110000000;
    int _58 = 0b11111111111111111111111111000000;
    int _59 = 0b11111111111111111111111111100000;
    int _60 = 0b11111111111111111111111111110000;
    int _61 = 0b11111111111111111111111111111000;
    int _62 = 0b11111111111111111111111111111100;
    int _63 = 0b11111111111111111111111111111110;
    int _64 = 0b11111111111111111111111111111111;

    System.out.println( " _0  = " + _0  );
    System.out.println( " _1  = " + _1  );
    System.out.println( " _2  = " + _2  );
    System.out.println( " _3  = " + _3  );
    System.out.println( " _4  = " + _4  );
    System.out.println( " _5  = " + _5  );
    System.out.println( " _6  = " + _6  );
    System.out.println( " _7  = " + _7  );
    System.out.println( " _8  = " + _8  );
    System.out.println( " _9  = " + _9  );
    System.out.println( " _10 = " + _10 );
    System.out.println( " _11 = " + _11 );
    System.out.println( " _12 = " + _12 );
    System.out.println( " _13 = " + _13 );
    System.out.println( " _14 = " + _14 );
    System.out.println( " _15 = " + _15 );
    System.out.println( " _16 = " + _16 );
    System.out.println( " _17 = " + _17 );
    System.out.println( " _18 = " + _18 );
    System.out.println( " _19 = " + _19 );
    System.out.println( " _20 = " + _20 );
    System.out.println( " _21 = " + _21 );
    System.out.println( " _22 = " + _22 );
    System.out.println( " _23 = " + _23 );
    System.out.println( " _24 = " + _24 );
    System.out.println( " _25 = " + _25 );
    System.out.println( " _26 = " + _26 );
    System.out.println( " _27 = " + _27 );
    System.out.println( " _28 = " + _28 );
    System.out.println( " _29 = " + _29 );
    System.out.println( " _30 = " + _30 );
    System.out.println( " _31 = " + _31 );
    System.out.println( " _32 = " + _32 );
    System.out.println( " _xx = " + _xx ); // -2147483648
    System.out.println( " _33 = " + _33 );
    System.out.println( " _34 = " + _34 );
    System.out.println( " _35 = " + _35 );
    System.out.println( " _36 = " + _36 );
    System.out.println( " _37 = " + _37 );
    System.out.println( " _38 = " + _38 );
    System.out.println( " _39 = " + _39 );
    System.out.println( " _40 = " + _40 );
    System.out.println( " _41 = " + _41 );
    System.out.println( " _42 = " + _42 );
    System.out.println( " _43 = " + _43 );
    System.out.println( " _44 = " + _44 );
    System.out.println( " _45 = " + _45 );
    System.out.println( " _46 = " + _46 );
    System.out.println( " _47 = " + _47 );
    System.out.println( " _48 = " + _48 );
    System.out.println( " _49 = " + _49 );
    System.out.println( " _50 = " + _50 );
    System.out.println( " _51 = " + _51 );
    System.out.println( " _52 = " + _52 );
    System.out.println( " _53 = " + _53 );
    System.out.println( " _54 = " + _54 );
    System.out.println( " _55 = " + _55 );
    System.out.println( " _56 = " + _56 );
    System.out.println( " _57 = " + _57 );
    System.out.println( " _58 = " + _58 );
    System.out.println( " _59 = " + _59 );
    System.out.println( " _60 = " + _60 );
    System.out.println( " _61 = " + _61 );
    System.out.println( " _62 = " + _62 );
    System.out.println( " _63 = " + _63 );
    System.out.println( " _64 = " + _64 );
4
Eddie B

Si un ajout d'entier déborde, alors le résultat est les bits de poids faible de la somme mathématique telle que représentée dans certaines assez grandes complément à deux. En cas de débordement se produit, alors le signe du résultat est pas le même que le signe du somme mathématique des deux opérandes valeurs.

http://Java.Sun.com/docs/books/jls/second_edition/html/expressions.doc.html#13510

3
user97370

Ceci est une solution de contournement donc vous pouvez toujours continuer à pratiquement infini . Je recommande un if (int> nearmax) puis passez à new int

int x = 2000000000;
x++;
int stacker = 0;
if (x > 2000000000)
{
int temp = x;
x = temp - 2000000000 
stacker++;
}

alors vous pouvez aussi dépiler si nécessaire ...

dire x = 0

x--;
if (x < 0 && stacker > 0)
{
int temp = x;
x = 2000000000 + temp;//plus because it's negative
stacker--;
}

cela donne 2000000000 x 2000000000 et je veux dire ... vous pouvez continuer à le faire alors ... ya ...

bien sûr, vous pouvez aller encore plus loin si vous voulez utiliser des nombres négatifs ...

0
user2455808