Question

J'ai une instruction if avec deux conditions (séparées par un opérateur OR), l'une des conditions couvre +70% des situations et prend beaucoup moins de temps à traiter/exécuter que la deuxième condition, donc dans un souci de rapidité, je veux seulement le deuxième condition à traiter si la première condition est évaluée comme fausse.

si j'ordonne les conditions de manière à ce que la première condition (la plus rapide) apparaisse en premier dans l'instruction if - dans les cas où cette condition est remplie et est évaluée vraie, la deuxième condition est-elle même traitée ?

if ( (condition1) | (condition2) ){
  // do this
}

ou devrais-je imbriquer deux instructions if pour vérifier uniquement la deuxième condition si la première est évaluée comme fausse ?

if (condition1){
  // do this
}else if (condition2){
  // do this
}

Je travaille en PHP, cependant, je suppose que cela peut être indépendant du langage.

Était-ce utile?

La solution

Pour C, C++, C#, Java et d'autres langages .NET, les expressions booléennes sont optimisées de sorte que dès que l'on en sait suffisamment, rien d'autre n'est évalué.

Une vieille astuce pour créer du code obscurci consistait à l'utiliser pour créer des instructions if, telles que :

a || b();

si "a" est vrai, "b()" ne sera jamais évalué, nous pouvons donc le réécrire dans :

if(!a)
    b();

et de même :

a && b();

deviendrait

if(a)
    b();

Veuillez noter que cela n'est valable que pour le || et && opérateur.Les deux opérateurs | et et est bit ou, et et, respectivement, et ne sont donc pas "optimisés".

MODIFIER:Comme mentionné par d'autres, essayer d'optimiser le code en utilisant la logique de court-circuit est très rarement du temps bien dépensé.

Optez d’abord pour la clarté, à la fois parce que c’est plus facile à lire et à comprendre.De plus, si vous essayez d'être trop intelligent, une simple réorganisation des termes pourrait conduire à un comportement très différent sans aucune raison apparente.

Deuxièmement, optez pour l'optimisation, mais seulement après le timing et le profilage.Beaucoup trop de développeurs effectuent une optimisation prématurée sans profilage.La plupart du temps, c'est complètement inutile.

Autres conseils

Presque toutes les langues effectuent une évaluation de court-circuit.Cela signifie que la deuxième condition n'est évaluée que si elle est absolument nécessaire.Pour que cela fonctionne, la plupart des langages utilisent le double tube, ||, et non le seul, |.

Voir http://en.wikipedia.org/wiki/Short-circuit_evaluation

En C, C++ et Java, l'instruction :

if (condition1 | condition2) {
  ...
}

évaluera les deux conditions à chaque fois et ne sera vrai que si l'expression entière est vraie.

La déclaration:


if (condition1 || condition2) {
  ...
}

évaluera condition2 seulement si condition1 c'est faux.La différence est significative si condition2 est une fonction ou une autre expression ayant un effet secondaire.

Il n'y a cependant aucune différence entre le || cas et le if/else cas.

J'ai vu beaucoup de ce type de questions ces derniers temps : l'optimisation au nième degré.

Je pense que cela a du sens dans certaines circonstances :

  1. La condition informatique 2 n'est pas une opération à temps constant
  2. Vous demandez strictement à des fins éducatives : vous voulez savoir comment fonctionne la langue, pas pour sauver 3nous.

Dans d'autres cas, s'inquiéter de la manière "la plus rapide" d'itérer ou de vérifier un conditionnel est idiot.Au lieu d'écrire des tests qui nécessitent des millions d'essais pour constater une différence enregistrable (mais insignifiante), concentrez-vous sur la clarté.

Lorsque quelqu'un d'autre (peut-être vous !) récupère ce code dans un mois ou un an, ce qui sera le plus important, c'est la clarté.

Dans ce cas, votre premier exemple est plus court, plus clair et ne nécessite pas de répétition.

Selon Cet article PHP effectue une évaluation des courts-circuits, ce qui signifie que si la première condition est remplie, la seconde n'est même pas évaluée.C'est assez simple à tester aussi (d'après l'article) :

<?php
/* ch06ex07 – shows no output because of short circuit evaluation */

if (true || $intVal = 5) // short circuits after true
{

echo $intVal; // will be empty because the assignment never took place
}

?>

Le court-circuit n'est pas destiné à l'optimisation.Son objectif principal est d'éviter d'appeler du code qui ne fonctionnera pas, mais qui aboutira à un test lisible.Exemple:

if (i < array.size() && array[i]==foo) ...

Notez que array[i] peut très bien subir une violation d'accès si i est hors de portée et faire planter le programme.Ce programme dépend donc certainement d'un court-circuit de l'évaluation !

Je pense que c'est la raison pour laquelle on écrit des expressions de cette façon bien plus souvent que des problèmes d'optimisation.

Même si l’utilisation du court-circuit à des fins d’optimisation est souvent excessive, il existe certainement d’autres raisons impérieuses de l’utiliser.Un tel exemple (en C++) est le suivant :

if( pObj != NULL && *pObj == "username" ) {
    // Do something...
}

Ici, on compte sur le court-circuit pour garantir que pObj a été alloué avant de le déréférencer.C'est bien plus concis que d'avoir imbriqué if déclarations.

Puisqu'il s'agit d'un langage étiqueté indépendant, j'interviendrai.Pour Perl au moins, la première option est suffisante, je ne connais pas PHP.Il évalue de gauche à droite et abandonne dès que la condition est remplie.

Dans la plupart des langages dotés d’une optimisation décente, le premier fonctionnera très bien.

Le | est un opérateur au niveau du bit en PHP.Cela ne signifie pas $a OR $b, exactement.Vous aurez envie d'utiliser le double-pipe.Et oui, comme mentionné, PHP effectue une évaluation des courts-circuits.De la même manière, si la première condition d'un && La clause est évaluée à false, PHP n'évalue pas non plus le reste de la clause.

VB.net a deux merveilleuses expressions appelées "OrElse" et "AndAlso".

OrElse se court-circuitera la première fois qu'il atteindra une évaluation True et exécutera le code que vous désirez.

If FirstName = "Luke" OrElse FirstName = "Darth" Then
   Console.Writeline "Greetings Exalted One!"
End If

AndAlso se court-circuitera la première fois avec une fausse évaluation et n'évaluera pas le code dans le bloc.

If FirstName = "Luke" AndAlso LastName = "Skywalker" Then
   Console.Writeline "You are the one and only."
End If

Je trouve ces deux éléments utiles.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top