9
votes

Overflow et contrôle de la gamme pour les opérations arithmétiques

Comment pouvons-nous vérifier si une opération arithmétique dépassera les limites supérieures du type de données avant de l'appliquer réellement.

Dites l'entrée en hautes enjouée en Java est 32767 et je me multiplie 328 * 100, je ne peux pas faire de comparaison avec short.max_value car une réponse après la multiplication serait déjà débordée et la réponse serait - 32736 qui est certainement plus petit que short.max_value

Prenez un autre exemple dire que je suis int valeur d'informatique 17 ^ 10 (17 à la puissance 10) dans A pour boucle. Comment puis-je savoir à quelle étape ma réponse a été débordée?

Ce court et int est un exemple. Pensez à ce problème dans la perspicacité plus importante ce qui peut être fait exactement pour tous les types de données.

J'ai essayé Googling mais n'ai trouvé aucun bon lien qui aide à comprendre le concept.


4 commentaires

Voulez-vous des avertissements? Voulez-vous que le nombre overflowed soit saturé? Voulez-vous qu'il arrête d'exécution? essayez {} catch (intgeroverflow) {} devrait être utile


@ Tuğrulbüyükışık try-attraper ne vient pas dans la photo ici, si une exception a été lancée, le programme s'arrêterait, puis seulement.


pas arrêté mais sévèrement ralenties oui


Vous pouvez être intéressé par les implémentations de Guava's Href = "http://docs.guava-libries.googlecode.com/git-history/release/javadoc/src-html/com/google/common/math/intmath. HTML # LINE.396 "REL =" NOFOOLS NOREFERRER "> INTMATH et LONGMATH pour une addition vérifiée, multiplication, etc.


3 Réponses :


5
votes

Il y a 3 méthodes possibles pour la vérification des débordements:

Utilisez un type plus grand et Down Downcast: jetez les entrées sur le plus grand type d'entier primitif et effectuez l'arithmétique de plus grande taille. Vérifiez chaque résultat intermédiaire pour débordement du type plus petit d'origine; lancer une arithméticepxception si la chèque de la plage échoue.

Pré-vérification des entrées: Vérifiez les entrées sur chaque opérateur arithmétique pour vous assurer que le débordement ne peut pas se produire. Encore une fois, lancez une arithméticepxception lorsque l'opération déborderait si elle a été effectuée si elle a été effectuée, sinon effectuez l'opération. xxx

Convertissez les entrées en objets de type BigInteger et effectuez toutes les arithmétiques à l'aide de méthodes BigInteger. Arithméticepxception jetée sur trop-plein.


2 commentaires

Cette question concerne tout sur Pré-cocher les entrées . Comment puis je faire ça. Je ne saurai pas cela avant de faire l'opération. Donc, au moins cette suggestion est exclue.


Cela dépendra du (s) opération (s) que vous avez l'intention d'effectuer. Ive a ajouté un chèque pour addition.



4
votes

Il existe un plan d'inclure de telles méthodes dans le package mathématique de Java 8, mais je ne sais pas quel est le statut actuel. Certains code source sont disponibles Ici . Je n'ai pas testé la mise en œuvre, mais cela pourrait vous donner des idées.

Par exemple, la multiplication INT est effectuée à l'aide de LIPS: P>

public static long multiplyExact(long x, long y) {
    long r = x * y;
    long ax = Math.abs(x);
    long ay = Math.abs(y);
    if (((ax | ay) >>> 31 != 0)) {
        // Some bits greater than 2^31 that might cause overflow
        // Check the result using the divide operator
        // and check for the special case of Long.MIN_VALUE * -1
       if (((y != 0) && (r / y != x)) ||
            (x == Long.MIN_VALUE && y == -1)) {
            throw new ArithmeticException("long overflow");
        }
    }
    return r;
}  


1 commentaires

Cela semble un peu intéressant. Merci @assylia. J'attendrai de voir si quelqu'un a plus de suggestions d'autre, je choisirai votre réponse.



2
votes

Je ferais le calcul en utilisant le plus grand type possible, BigInteger / BigDecimal. J'attribuerais ensuite la valeur au type approprié en fonction de sa magnitude ... Il existe de manière intéressante certaines méthodes utiles pour cela ... ShortvalueExtract lancera une arithmétricexception si la valeur ne peut pas être contenue dans une courte ..

BigDecimal result = BigDecimal.valueOf(328).multiply(
        BigDecimal.valueOf(100));
try {
    short shortResult = result.shortValueExact();
} catch (ArithmeticException e) {
    // overflow
    System.out.println("Overflow!");
}

try {
    int intResult = result.intValueExact();
} catch (ArithmeticException e) {
    // overflow
}


0 commentaires