8
votes

Pourquoi l'ordre des expressions est-il important

Supposons que j'ai un si condition: xxx

suppose maintenant que a est plus susceptible de recevoir une valeur vraie puis B , pourquoi est-ce que je me soucie de savoir lequel est à gauche?

Si je les mettez les deux dans les supports si , je sais (comme programmeur du code) que les deux parties sont nécessaires.

Le La chose est que mon professeur a écrit sur ses remarques de cours que je devrais mettre la "variable plus probable pour recevoir un vrai" à gauche.

Quelqu'un peut-il expliquer l'avantage? D'accord, je le mets à gauche ... Qu'est-ce que je gagne? Durée ?


4 commentaires

N'oubliez pas que si votre état est ou placé la condition plus susceptible d'être vrai en premier, car c'est suffisant pour savoir que toute la condition sera vraie. Si votre état est un et mettez la condition qui va être faux d'abord parce que cela suffit à avoir tout votre état faux. Java vous permet également d'évaluer les deux conditions (pas courtes circuits) en utilisant '|' et des opérateurs '&'.


@gersonzaragocine - Le | et et Les opérateurs de Java (et C et C ++) sont des opérateurs bitwises. Pour les valeurs booléennes, ils agissent comme vous le décrivez, mais ce n'est pas leur but.


@Petebecker Cet opérateur dans JLS sont appelés opérateurs "Bitwise et logique". Veuillez vérifier cette section, ils sont définis à la fin docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#JLS-15 .22 . C'est un exemple clair de surcharge de l'opérateur.


@gersonzaragocin - Merci. Pour les types booléens, ils sont documentés pour effectuer des opérations logiques et fonctionnent car les valeurs booléennes sont 1 et 0; Ils font toujours des opérations bitwises. Cependant, pour d'autres types, ils ne donnent pas le même résultat que || ou `&& ', qui était mon point.


9 Réponses :


5
votes

Selon Javadoc

the && et || Les opérateurs effectuent des opérations conditionnelles et conditionnelles à deux expressions booléennes. Ces opérateurs présentent un comportement "à court-circuit", ce qui signifie que le deuxième opérande est évalué que si nécessaire

Donc, si la déclaration vraie vient en premier dans la commande, elle court-circuit le deuxième opérande au moment de l'exécution.


1 commentaires

véritables courts-circuits pour || , pas pour && . Faux courts-circuits pour && , pas pour || .



2
votes

Si l'expression à gauche est vraie, il n'est pas nécessaire d'évaluer l'expression à droite, et il peut donc être optimisé au moment de l'exécution. Ceci est une technique appelée court-circuit. Donc, en plaçant l'expression plus susceptible d'être vrai à gauche, nous pouvons nous attendre à ce que notre programme fonctionne mieux que s'il s'agissait de l'inverse.


1 commentaires

Décrire l'évaluation de court-circuit comme une optimisation implique qu'il est facultatif. Ce n'est pas. C'est le comportement mandaté par la norme.



2
votes

Vous devez placer la condition plus susceptible d'être true d'abord parce que cela entraînera la déclaration IF à court-circuit. Ce qui signifie qu'il n'évaluera pas le reste de la déclaration de si, car il saura déjà que la réponse est vraie. Cela rend le code plus efficace.

Ceci est particulièrement utile lorsque votre instruction IF évalue des objets coûteux: P>

if(doExpensiveCheck1() || doExpensiveCheck2()) { }


0 commentaires

9
votes

je le mets à gauche ... Qu'est-ce que je gagne? Temps d'exécution ?

parce que || opérateur en C ++ utilise Évaluation de court-circuit .
I.E: B est évasé uniquement si A est évalué à un false .

Toutefois, notez que, dans l'évaluation de court-circuit C ++, est garantie pour les types de données "intégrés" et non des types de données personnalisés.


5 commentaires

@ron qu'est-ce que tu parles d'autre?


@ron - Je soupçonne que c'est exactement ce que signifie votre professeur.


@Als: D'accord, donc fondamentalement, la réponse est d'exécution! j'ai compris .


@ron La différence n'est pas seulement d'exécuter. Les || et && sont également une sorte de structure de contrôle. Pensez à ce code (pas très bon): si (a || this_will_crash_if_a_is_true ()) . Lorsque vous l'exécutez avec A == 1 , il n'y a pas de crash: la fonction "crashy" n'est jamais appelée à cause de l'évaluation de court-circuit.


L'évaluation de court-circuit est garantie pour l'opérateur intégré || et opérateur && , quel que soit le type de données. Vous n'obtenez pas d'évaluation de court-circuit pour un type de données défini par l'utilisateur qui surcharge ces opérateurs, car l'opérateur surchargé est une fonction normale et que les deux arguments doivent être transmis à cette fonction.



2
votes

Dans de nombreux cas, il n'y a pas de différence pratique en dehors d'une infime d'amélioration de la performance. Lorsque cela devient utile, c'est si vos chèques sont des appels de fonction très coûteux (peu probable) ou vous devez vérifier les choses en ordre. Dis par exemple, vous voulez vérifier une propriété sur quelque chose et vérifier si quelque chose est nul tout d'abord, vous pourriez faire quelque chose comme:

si (a! = nil && a.attribute == valide) {}


0 commentaires

0
votes

Oui, c'est exactement, vous gagnez de l'heure, cela ne semblera pas grand chose pour une opération, mais vous devez garder à l'esprit que les opérations seront répétées des millions de fois

Pourquoi effectuer deux évaluations quand on suffit est la logique


0 commentaires

25
votes

Il ne s'agit pas seulement de choisir la condition la plus probable à gauche. Vous pouvez également avoir une protection sécurisée à gauche pour le sens que vous ne pouvez avoir qu'une seule commande. Considérons xxx pré>

Vous ne pouvez pas échanger la commande ici car la première condition protège la seconde de lancer une NPE. P>

De même, vous pouvez avoir P>

if (s != null && s.length() > 0) // if the String is not empty


1 commentaires

J'aimerais pouvoir uppoter cela un couple de plus - l'exactitude est une considération plus importante que "qui est plus probable" en ce qui concerne le placement de l'opérande avec les opérateurs de court-circuit. Aussi - beaux exemples du monde réel; Le second est particulièrement important pour un novice à comprendre, car c'est une idiome très courante.



0
votes

au moment de l'exécution si (A || B) testera un premier, si A est vrai, il ne perdra pas le test de temps Bori le compilateur sera une exécution à l'avance. Par conséquent, si A est plus susceptible d'être vrai que B Ce test est également susceptible de couper 1 ligne. Le nombre total de lignes non exécutées est minuscule sur une seule ligne, mais elle est énorme si la déclaration est imbriquée dans une boucle d'une sorte (pour, pendant la récession ou des requêtes liées à la base de données). Par exemple, par exemple, nous avons 1 million de minutes pour tester des données dans une base de données à 1 minute par enregistrement (30 secondes pour la condition A et 30 secondes pour la condition B). Soit A 80% de chances d'être vrai et b avoir 20% de chances d'être vrai. Le temps total requis si vous mettez un premier à 600-000 heures, il est encore 900-000 heures si vous mettez B PREMIER.Si A est testé d'abord [(0,8 * 1 millions heures) * 0,5ms + (0,2 * 1 Million) * 1min] === 6000-000hrs: Si B est testé d'abord [(0,2 * 1 Million heures) * 0,5ms + (0,2 * 1 Million heures) * 1min] === 9000-000hrs. Cependant, vous remarquerez que la différence est moins importante si la probabilité de devenir vrai est plus proche de celle de b.


1 commentaires

C'est court-circuit et déjà couvert dans l'une des réponses



0
votes
public class Main
{
    public static void main(String[] args) {
        System.out.println("Hello World");
        Integer a = null;
        Integer b = 3;
        Integer c = 5;

        if(a != null && a == 2){
            System.out.println("both");
        }else{
            System.out.println("false");
        }
    }
}
Hello World
false  

0 commentaires