Вопрос

У меня есть оператор 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-й степени.

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

<Ол>
  • Вычислительное условие 2 не является операцией с постоянным временем
  • Вы спрашиваете строго в образовательных целях - вы хотите знать, как работает язык, а не сохранять 3us.
  • В других случаях беспокоюсь о " самом быстром " Способ итерации или проверки условного кода глупый. Вместо того, чтобы писать тесты, которые требуют миллионов испытаний, чтобы увидеть любую записываемую (но незначительную) разницу, сосредоточьтесь на ясности.

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

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

    Согласно этой статье 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
    

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

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top