9
votes

Long + long pas plus gros que long.max_value

Si j'ai une affectation xxx

est un moyen facile de vérifier que A + B n'est pas plus grand / plus petit que long.max_value < / code> / long.min_value ?


5 commentaires

Veuillez vous reporter au Comment formater Boîte à droite de la zone de texte de la question et le [?] [?] LIEN au-dessus de celui-ci (et l'aperçu ci-dessous) pour savoir comment correctement questions de format.


En assembleur, il serait possible de vérifier le drapeau porter ?


J'ai supprimé la balise [Homework], comme l'OP mentionné dans un fil de commentaire que ce n'était que là par accident.


Ah, j'ai mal interprété la mission à signifier l'affectation :)


Aha! Le mystère, expliqué: c'était juste une mission variable.


4 Réponses :


17
votes

en utilisant GUAVA , c'est aussi simple que

long c = LongMath.checkedAdd(a, b); // throws an ArithmeticException on overflow


11 commentaires

+1 pour GUAVA. Même si la comparaison (comme suggérée à l'origine par moi) peut éventuellement fonctionner (bien que je suis trop somnolent pour le penser correctement), préférez la fonction prête à l'emploi


Divulgation complète: Je suis l'auteur de LongMath et le reste de GUAVA'S Common.Math Package ... Mais @bozho est correct qu'il est généralement préférable de compter sur le code de la bibliothèque plutôt que de rouler votre propre implémentation. (En particulier, ce code a déjà été testé très de manière exhaustive, vous n'avez donc pas besoin!)


Très cool. L'ajout d'une autre bibliothèque entière peut être surchargée pour un cas aussi simple (détecter le débordement dans ce cas est trivial), mais si vous êtes déjà en utilisant GUAVA ...


En effet. Et je pourrais mentionner que com.google.common.math a beaucoup de friandises au-delà de l'arithmétique vérifiée. ;) En outre, chaque chèque de trop-plein n'est pas ce trivial - en particulier, vérifiant le débordement lorsque la multiplication des longs est significativement plus difficile: docs.guava-librarles.gitoglecode.com/git-history/release/java doc / ...


Ce n'est peut-être pas le meilleur pour une mission, mais il est certainement intéressant d'examiner la bibliothèque.


D'accord. (En toute honnêteté, j'ai véritablement manqué l'étiquette des devoirs sur la question, qui utilise moins les bibliothèques extérieures appropriées.)


Y a-t-il une raison pour laquelle a + b n'est pas assez bon pour vérifier le débordement? Évidemment, si nous voulons aussi vérifier les sous-ensembles, nous avons besoin de la tromperie habituelle, mais sinon cela devrait aller. S'il y a un débordement, nous calculons A + B - 2 ^ 32 après tout ce qui est garanti toujours négatif (et il ne peut y avoir de débordement si A ou B sont négatifs).


@Louis Après avoir lu mon premier poste, je l'ai supprimé et je l'ai retraité, désolé pour la confusion. J'espère que cela rend plus clair!


L'étiquette de devoirs s'est effectivement obtenu par accident. Merci pour l'explication approfondie sur le fonctionnement de celui-ci et la suggestion de la bibliothèque. Difficile de choisir quelle réponse accepte, les deux sont très bons :)


@Voo: débordement, débordement, les deux sont diaboliques et mauvais et plus équivalents. Je viens d'utiliser le terme "débordement" pour les deux cas.


@Kaurkase: En règle générale, lorsqu'il s'agit de trucs de mathématiques Finicky - qui déborde certainement, je vous recommande vivement d'utiliser des solutions de bibliothèque qui ont déjà été testées pour vous. (Même si ce n'est pas une bibliothèque, j'ai écrit, heh.) Il y a juste de nombreuses façons de viser ces choses, comme je l'ai découvert tout en écrivant la bibliothèque ...



0
votes

Une option serait d'utiliser la classe BigInteger pour effectuer le calcul exact, puis vérifiez si le résultat est supérieur ou inférieur à la valeur en question. Par exemple: xxx

espère que cela aide!


3 commentaires

Si vous allez aller de l'avant et que vous utilisez la pleine puissance de biginteger , vous pouvez simplement vérifier mybigint.bitlength () , je suis presque positif.


@Louiswasserman correct à cause du moindre que, sinon ce serait un désactivé par un. Je ne pense pas que l'une des deux options soit lisible cependant, et celle de la réponse ne prend que de long.Max_Value, pas de long.min_value ...


J'ai convenu que cela est moins lisible qu'il ne pourrait l'être. Pour référence, bien que je disais que l'approche de BigInteger est la solution la plus lisible de vérifier le débordement sur multiplication , si vous n'êtes pas disposé à utiliser une bibliothèque.



0
votes

La route simple: xxx

Il vous suffit d'espérer que cela ne sera pas optimisé pour (A + B) / 2 < / p>


2 commentaires

Je ne crois pas que cela fonctionne correctement. Prendre a = long.max_value et b = 1. Ensuite, il y a clairement un débordement si vous ajoutez les deux valeurs, mais si vous les coupez en deux, A / 2 = long.max_value / 2 et B / 2 = 0, donc un / 2 + B / 2 <= long.max_value.


@Templatetypedef J'ai corrigé cette friandise (ajouté le débordement)



13
votes

Ce n'est qu'un problème s'ils ont le même signe (et sont tous deux les deux ! 0 code>), car sinon vous êtes à l'abri de débordement. Si le débordement survient, le signe du résultat se retournera. Donc:

long r = a + b;
if ( (a < 0 && b < 0 && r >= 0) ||
     (a > 0 && b > 0 && r <= 0) ) {
    // Overflow occurred
}


3 commentaires

Voté, le plus simple, le plus lisible et le meilleur moyen. Espérons que le parcours n'ira pas pour une méthode mathématique plus «optimisée».


@ wwwowstead, si le compilateur est suffisamment intelligent, il peut utiliser le drapeau "Carry" de la CPU, la solution est donc assez bonne. De retour dans la journée, le seul arithmétique a été fait via le port.


Même si nous savons maintenant que ce n'est pas des devoirs, gardez mon uppot pour une solution facile à comprendre.