2010-09-15 28 views
2

Si j'ai une expression booléenne pour vérifierEst-ce que l'ordre d'expression pour vérifier dans l'état booléenne affecter les performances

(A && B) 

Si A se trouve faux sera la langue la peine de vérifier B? Est-ce que cela varie d'une langue à l'autre?

La raison pour laquelle je demande est que je me demande si c'est le cas que B est cochée, même si A est faux alors ne serait pas

if (A) { 
    if(B) { 

    } else { 
    // code x 
    } 
} else { 
    // code x 
} 

être légèrement plus rapide que

if (A && B) { 

} else { 
    // code x 
} 
+0

Cette question n'est pas indépendante de la langue. Cela ressemble à un langage de la famille C. Dans ce cas, il s'agit d'un opérateur de court-circuit. –

Répondre

4

Cette dépend de la langue. La plupart des langues implémentent A && B en tant qu'opérateur de court-circuit, ce qui signifie que si A est évalué à false, B ne sera jamais évalué. Il y a un detailed list on Wikipedia.

1

De nombreuses langues (y compris la quasi-totalité des langages accolades, comme C/C++/Java/C#) offrent une évaluation booléenne en court-circuit. Dans ces langues, si A est faux alors B ne sera pas évalué. Vous aurez besoin de voir (ou demander) si cela est vrai pour votre langue spécifique, ou s'il y a un moyen de le faire (VB a AndAlso, par exemple). Si vous pensez que votre langue ne la prend pas en charge, vous devrez également déterminer si le coût de l'évaluation de B vaut la peine de conserver deux parties de code identiques - et le potentiel de doubler l'empreinte du cache (pas mentionner toutes les branches supplémentaires) qui proviendrait de faire cette duplication à chaque fois.

1

Presque toutes les langues implémente quelque chose appelé short-circuit evaluation, ce qui signifie que, oui, (A & & B) n'évaluera pas l'B si A est faux. Cela prend également effet si vous écrivez:

if (A || B) { 
    ... 
} 

et A est vrai. Cela vaut la peine de se rappeler si B peut prendre beaucoup de temps à charger, mais en général ce n'est pas quelque chose à s'inquiéter.

Comme un peu d'histoire, dans mon esprit c'est un peu d'une partie mal de LISP parce que le code comme ceci:

(if (and (= x 5) (my-expensive-query y)) "Yes" "No") 

ne sont pas en fonctions, mais plutôt que l'on appelle les « formes spéciales » (c'est-à-dire "et" ne pouvait pas être défoncé ici).

1

Cela dépendrait à 100% de la façon dont le langage compile ledit code. Tout est possible :)

Existe-t-il une langue spécifique dont vous vous interrogez?

1

En bref, non. Une double branche implique diverses formes de prédiction de branche. Si A et B sont simples à évaluer, il peut être plus rapide de faire si (A & & B) d'une manière non court-circuit que si (A) si (B). En outre, vous avez dupliqué le code dans le second formulaire. C'est presque toujours (exception à toutes les règles .. je suppose) mauvais et bien pire que tout gain. Deuxièmement, c'est le type de micro-optimisation que vous donnez à l'interpréteur de langage, au JIT ou au compilateur.

+0

Je pensais aux cas où B est une condition vraiment complexe (dans l'application sur laquelle je travaille actuellement, il y a environ 5 ou 6 inégalités avec l'opérateur || entre eux, et cela est souvent appelé au chargement de la page) ... mais comme javascript utilise des courts-circuits, il semble que ce ne sera pas un problème – wheresrhys

+0

L'ordre des opérandes dans une évaluation de court-circuit n'est souvent pas une micro-optimisation. Parfois, c'est sémantiquement important (comme 'p && p-> a' dans un programme C), et parfois c'est important pour la performance. Si A est rapide et renvoie généralement faux, et B prend beaucoup de temps à calculer, A && B peut être significativement plus rapide que B && A, et comme il y a une différence sémantique, le compilateur ne peut généralement pas les réordonner. –

+0

Si vous êtes en C, pourquoi ne pas utiliser 'if (type * p = some_init()) {p-> a; } ' – Puppy

0

Comme d'autres l'ont dit, cela dépend de la langue et/ou du compilateur.Pour moi, je me fiche de la rapidité ou de la lenteur de la mise en court-circuit ou non, le besoin de dupliquer le code est un gâchis. Si A et B sont réellement des appels qui ont des effets secondaires (c'est-à-dire qu'ils ne font pas simplement renvoyer une valeur propre à être comparée), je dirais que ces appels doivent être transformés en affectations de variables Comparaison. Peu importe que vous ayez toujours besoin de ces effets secondaires ou que vous en ayez seulement besoin conditionnellement, le code sera plus lisible si vous ne dépendez pas de l'existence ou non d'un court-circuit.

Ce dernier point sur la lisibilité est basé sur mon sentiment que la réduction du besoin de se référer à la documentation externe améliore la lisibilité. Lire un livre avec un tas de nouveaux mots qui nécessitent des recherches de dictionnaire est beaucoup plus difficile que de lire ce même livre lorsque vous avez déjà le vocabulaire nécessaire. Dans ce cas, le court-circuit est invisible, donc toute personne qui a besoin de le regarder ne saura même pas qu'ils doivent le rechercher.

+0

Je vais utiliser C pour un exemple. Si A est une expression qui attribue une valeur de pointeur à 'p', qui pourrait être valide ou null, et B est une expression qui utilise' p' et a d'autres effets secondaires, alors vous ne pouvez pas simplement évaluer A et B et ensuite utiliser leurs valeurs de vérité. Le court-circuitage n'est pas non plus une partie obscure de la langue, il n'est donc pas nécessaire de l'éviter de peur de dérouter quelqu'un. –

+0

@David Thornley: Dans votre exemple, vous pouvez facilement vérifier si la valeur de retour de A est valide avant de passer à B. Mon inquiétude avec l'évaluation conditionnelle par court-circuit peut être mise en opposition avec l'opérateur conditionnel (?). Au moins, il a une syntaxe explicite, contrairement au court-circuit. Pour quelqu'un venant d'une langue qui n'offre aucun opérateur conditionnel, le besoin de vérifier la documentation est évident. Le court-circuit ne fournit pas une telle indication. FWIW, je suis probablement partial parce que je viens d'une langue qui ne l'a pas eu, et seul le court-circuit m'a fait trébucher. – jadero

+0

Je maintiens ma position antérieure: les opérateurs de court-circuit font partie de C et sont couramment utilisés en tant que tels. Tout programmeur C compétent l'utilisera correctement, et tout programmeur compétent dans un certain nombre d'autres langues s'attend à un comportement en court-circuit. Je ne suis pas d'accord avec l'idée de ne pas l'utiliser parce qu'un vrai novice pourrait être confus. –