если оптимизация условия оператора - PullRequest
5 голосов
/ 29 августа 2008

У меня есть оператор if с двумя условиями (разделенными оператором ИЛИ), одно из условий покрывает + 70% ситуаций и занимает гораздо меньше времени для обработки / выполнения, чем второе условие, поэтому в интересах скорости I хотите, чтобы второе условие было обработано, только если первое условие имеет значение false.

если я упорядочу условия так, чтобы первое условие (более быстрое) появилось в операторе if первым - в тех случаях, когда это условие выполняется и оценивается как истинное, вообще обрабатывается второе условие?

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

или мне нужно вложить два оператора if, чтобы проверять только второе условие, если первое оценивается как ложное?

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

Я работаю в PHP, однако я предполагаю, что это может быть не зависит от языка.

Ответы [ 11 ]

9 голосов
/ 29 августа 2008

Для языков C, C ++, C #, Java и других .NET булевы выражения оптимизированы так, что, как только будет известно достаточно, ничего больше не будет оценено.

Старый трюк для создания запутанного кода состоял в том, чтобы использовать это для создания операторов if, таких как:

a || b();

если «a» истинно, «b ()» никогда не будет оцениваться, поэтому мы можем переписать его в:

if(!a)
    b();

и аналогично:

a && b();

станет

if(a)
    b();

Обратите внимание , что это действительно только для || и && оператор. Два оператора | и & является побитовым или, и и, соответственно, и поэтому не «оптимизированы».

EDIT: Как уже упоминалось, попытка оптимизировать код с помощью логики короткого замыкания очень редко тратится время.

Сначала идите для ясности, потому что это легче читать и понимать. Кроме того, если вы попытаетесь быть слишком умным, простое изменение порядка терминов может привести к совершенно другому поведению без видимой причины.

Во-вторых, идите на оптимизацию, но только после синхронизации и профилирования. Слишком много разработчиков делают преждевременную оптимизацию без профилирования. В большинстве случаев это совершенно бесполезно.

3 голосов
/ 29 августа 2008

В C, C ++ и Java утверждение: <pre> if (condition1 | condition2) { ... }

будет оценивать оба условия каждый раз и будет истинным, если все выражение верно.

Утверждение:

<code>
if (condition1 || condition2) {
  ...
}

будет оценивать condition2, только если condition1 равно false. Разница значительна, если условие2 является функцией или другим выражением с побочным эффектом.

Однако между корпусом || и if / else нет никакой разницы.

3 голосов
/ 29 августа 2008

Практически каждый язык выполняет оценку короткого замыкания. Значение второго условия оценивается только в том случае, если оно абсолютно необходимо. Чтобы это работало, большинство языков используют двойную трубу, ||, а не одну, |.

См. http://en.wikipedia.org/wiki/Short-circuit_evaluation

2 голосов
/ 17 сентября 2008

Короткое замыкание не для оптимизации. Его главная цель - избежать вызова кода, который не будет работать, но все же приведет к читабельному тесту. Пример:

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

Обратите внимание, что массив [i] может очень хорошо получить нарушение прав доступа, если я вне диапазона и вывести программу из строя. Таким образом, эта программа, безусловно, зависит от короткого замыкания оценки!

Я полагаю, что это причина написания выражений гораздо чаще, чем проблемы оптимизации.

2 голосов
/ 29 августа 2008

Согласно этой статье PHP выполняет оценку короткого замыкания, что означает, что при выполнении первого условия второе даже не оценивается. Это также легко проверить (из статьи):

<?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
}

?>
2 голосов
/ 29 августа 2008

В последнее время я видел много таких вопросов - оптимизация до n-й степени.

Я думаю, что это имеет смысл при определенных обстоятельствах:

  1. Условие вычисления 2 не является операцией с постоянным временем
  2. Вы спрашиваете строго в образовательных целях - хотите знать, как работает язык, а не экономить 3us.

В других случаях беспокоиться о «самом быстром» способе итерации или проверки условия глупо. Вместо того, чтобы писать тесты, которые требуют миллионов испытаний, чтобы увидеть любую записываемую (но незначительную) разницу, сосредоточьтесь на ясности.

Когда кто-то другой (может быть вы!) Подберет этот код через месяц или год, самое важное - ясность.

В этом случае ваш первый пример короче, понятнее и не требует повторения.

1 голос
/ 30 августа 2008

Хотя использование короткого замыкания в целях оптимизации часто бывает излишним, существуют и другие веские причины для его использования. Один из таких примеров (в C ++) следующий:

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

Здесь используется короткое замыкание, чтобы гарантировать, что pObj было выделено до его разыменования. Это гораздо более кратко, чем иметь вложенные операторы if.

0 голосов
/ 30 августа 2008

VB.net имеет два замечательных выражения под названием «OrElse» и «AndAlso»

OrElse замкнет себя в первый раз, когда достигнет истинной оценки, и выполнит нужный код.

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

AndAlso также будет замыкать себя в первый раз, когда это ложная оценка, и не будет оценивать код в блоке.

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

Я считаю, что оба они полезны.

0 голосов
/ 29 августа 2008

| - побитовый оператор в PHP. Это не значит $a OR $b, точно. Вы хотите использовать двойную трубу. И да, как уже упоминалось, PHP выполняет оценку короткого замыкания. Аналогичным образом, если первое условие предложения && оценивается как ложное, PHP также не оценивает остальную часть предложения.

0 голосов
/ 29 августа 2008

В большинстве языков с достойной оптимизацией первый будет работать просто отлично.

...