web-dev-qa-db-fra.com

Java Integer compareTo () - pourquoi utiliser la comparaison par rapport à la soustraction?

J'ai trouvé que Java.lang.Integer l'implémentation de la méthode compareTo se présente comme suit:

public int compareTo(Integer anotherInteger) {
    int thisVal = this.value;
    int anotherVal = anotherInteger.value;
    return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}

La question est de savoir pourquoi utiliser la comparaison au lieu de la soustraction:

return thisVal - anotherVal;
78
Vladimir

Cela est dû à un débordement d'entier. Lorsque thisVal est très grand et que anotherVal est négatif, soustraire ce dernier du premier donne un résultat plus grand que thisVal qui peut déborder vers la plage négative.

91
Itay Maman

La soustraction "astuce" pour comparer deux valeurs numériques est cassée !!!

        int a = -2000000000;
        int b =  2000000000;
        System.out.println(a - b);
        // prints "294967296"

Ici, a < b, encore a - b est positif.

N'UTILISEZ PAS cet idiome. Ça ne marche pas.

De plus, même si ça marche, ça [~ # ~] pas [~ # ~] apporter une amélioration significative des performances, et peut en fait lisibilité des coûts.

Voir également

  • Puzzlers Java Puzzle 65: Une étrange saga de nature suspecte

    Ce puzzle a plusieurs leçons. Le plus spécifique est: N'utilisez pas de comparateur basé sur la soustraction, sauf si vous êtes sûr que la différence entre les valeurs ne sera jamais supérieure à Integer.MAX_VALUE. Plus généralement, méfiez-vous du débordement de int. Une autre leçon est que vous devez éviter le code "intelligent". Efforcez-vous d'écrire un code clair et correct et ne l'optimisez pas sauf si cela s'avère nécessaire.

63
polygenelubricants

Pour parler simplement, le type int n'est pas assez grand pour stocker la différence entre deux valeurs arbitraires int. Par exemple, la différence entre 1,5 milliard et -1,5 milliard est de 3,0 milliards, mais int ne peut pas contenir des valeurs supérieures à 2,1 milliards.

9
fredoverflow

C'est peut-être pour éviter les débordements/sous-débordements.

3
Adamski

En plus du problème de débordement, vous devriez noter que la version avec soustraction ne donne pas les mêmes résultats.

  • La première version compareTo renvoie l'une des trois valeurs possibles: -1, 0 ou 1.
  • Si vous remplacez la dernière ligne par une soustraction, le résultat peut être n'importe quelle valeur entière.

Si vous savez qu'il n'y aura pas de débordement, vous pouvez utiliser quelque chose comme ceci:

public int compareTo(Integer anotherInteger) {
    return sign(this.value - anotherInteger.valuel);
}
1
PauliL