оптимизация условий оператора if
-
09-06-2019 - |
Вопрос
У меня есть оператор if с двумя условиями (разделенными оператором OR), одно из условий охватывает + 70% ситуаций и требует гораздо меньше времени для обработки / выполнения, чем второе условие, поэтому в интересах скорости я хочу, чтобы второе условие обрабатывалось только в том случае, если первое условие принимает значение false.
если я упорядочу условия так, чтобы первое условие (более быстрое) сначала появлялось в операторе if - в тех случаях, когда это условие выполняется и принимает значение true, обрабатывается ли вообще второе условие?
if ( (condition1) | (condition2) ){
// do this
}
или мне нужно было бы вложить два оператора if, чтобы проверять второе условие только в том случае, если первое принимает значение false?
if (condition1){
// do this
}else if (condition2){
// do this
}
Я работаю на PHP, однако я предполагаю, что это может не зависеть от языка.
Решение
Для языков C, C ++, C #, Java и других .NET логические выражения оптимизированы таким образом, что, как только становится известно достаточно, больше ничего не вычисляется.
Старый трюк для выполнения запутанного кода состоял в том, чтобы использовать это для создания операторов if, таких как:
a || b();
если "a" равно true, "b()" никогда не будет вычислено, поэтому мы можем переписать его в:
if(!a)
b();
и точно так же:
a && b();
стал бы
if(a)
b();
Пожалуйста, обратите внимание что это действительно только для операторов || и && .Два оператора | и & являются побитовыми или, и и, соответственно, и поэтому не "оптимизированы".
Редактировать:Как упоминали другие, попытки оптимизировать код с использованием логики короткого замыкания очень редко тратят время с пользой.
Сначала стремитесь к ясности, потому что так легче читать и понимать.Кроме того, если вы попытаетесь быть слишком умным, простое изменение порядка терминов может привести к совершенно иному поведению без какой-либо видимой причины.
Во-вторых, приступайте к оптимизации, но только после определения времени и профилирования.Слишком многие разработчики проводят преждевременную оптимизацию без профилирования.Большую часть времени это совершенно бесполезно.
Другие советы
Практически каждый язык выполняет оценку короткого замыкания. Значение второго условия оценивается только в том случае, если оно абсолютно необходимо. Чтобы это работало, большинство языков используют двойную трубу, ||, а не одну, |.
См. http://en.wikipedia.org/wiki/Short-circuit_evaluation р>
В C, C ++ и Java выражение: <Код> код>
if (condition1 | condition2) {
...
}
будет оценивать оба условия каждый раз и будет истинным, если все выражение истинно. Р>
Заявление:
if (condition1 || condition2) {
...
}
будет оценивать condition2
, только если condition1
равно false. Разница значительна, если условие2 является функцией или другим выражением с побочным эффектом. Р>
Однако между делом ||
и делом if
/ else
не существует никакой разницы.
В последнее время я видел много таких вопросов - оптимизация до n-й степени.
Я думаю, что это имеет смысл в определенных обстоятельствах:
<Ол>В других случаях беспокоюсь о " самом быстром " Способ итерации или проверки условного кода глупый. Вместо того, чтобы писать тесты, которые требуют миллионов испытаний, чтобы увидеть любую записываемую (но незначительную) разницу, сосредоточьтесь на ясности.
Когда кто-то другой (может быть вы!) подберет этот код через месяц или год, самое важное будет ясность.
В этом случае ваш первый пример короче, понятнее и не требует повторения.
Согласно этой статье 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
}
?>
Короткое замыкание не для оптимизации. Его главная цель - избежать вызова кода, который не будет работать, но все же приведет к читабельному тесту. Пример: р>
if (i < array.size() && array[i]==foo) ...
Обратите внимание, что массив [i] может очень хорошо получить нарушение прав доступа, если я вне диапазона и вывести программу из строя. Таким образом, эта программа, безусловно, зависит от короткого замыкания оценки!
Я считаю, что это причина написания выражений гораздо чаще, чем проблемы оптимизации.
Хотя использование короткого замыкания в целях оптимизации часто является излишним, существуют и другие веские причины для его использования. Один из таких примеров (в C ++) следующий:
if( pObj != NULL && *pObj == "username" ) {
// Do something...
}
Здесь используется короткое замыкание, чтобы гарантировать, что pObj
было выделено до его разыменования. Это гораздо более сжато, чем вложенные операторы if
.
Поскольку это не зависит от языка тегов, я включу его. По крайней мере, для Perl достаточно первого варианта, я не знаком с PHP. Он оценивает слева направо и выпадает, как только условие выполнено.
В большинстве языков с приличной оптимизацией первый будет работать просто отлично.
|
- побитовый оператор в PHP. Это точно не означает $ a OR $ b
. Вы хотите использовать двойную трубу. И да, как уже упоминалось, PHP выполняет оценку короткого замыкания. Аналогичным образом, если первое условие предложения & amp;
оценивается как ложное, PHP также не оценивает остальную часть предложения.
На 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
Я считаю, что оба они полезны.