Pergunta

Eu tenho uma instrução if com duas condições (separadas por um operador OR), uma das condições cobre +70% das situações e leva muito menos tempo para processar/executar do que a segunda condição, portanto, no interesse da velocidade, eu só quero o segunda condição a ser processada se a primeira condição for avaliada como falsa.

se eu ordenar as condições para que a primeira condição (a mais rápida) apareça primeiro na instrução if - nas ocasiões em que essa condição é atendida e avaliada como verdadeira, a segunda condição é processada?

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

ou eu precisaria aninhar duas instruções if para verificar apenas a segunda condição se a primeira for avaliada como falsa?

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

Estou trabalhando em PHP, no entanto, presumo que isso possa ser independente de linguagem.

Foi útil?

Solução

Para C, C++, C#, Java e outras linguagens .NET, as expressões booleanas são otimizadas para que, assim que o suficiente for conhecido, nada mais seja avaliado.

Um truque antigo para criar código ofuscado era usar isso para criar instruções if, como:

a || b();

se "a" for verdadeiro, "b()" nunca seria avaliado, então podemos reescrevê-lo em:

if(!a)
    b();

e da mesma forma:

a && b();

se tornaria

if(a)
    b();

Observe que isso é válido apenas para o || e && operador.Os dois operadores | & & é bit -in ou, e, e, respectivamente, e, portanto, não são "otimizados".

EDITAR:Conforme mencionado por outros, tentar otimizar o código usando lógica de curto-circuito raramente é um tempo bem gasto.

Primeiro busque clareza, porque é mais fácil de ler e entender.Além disso, se você tentar ser muito inteligente, uma simples reordenação dos termos poderá levar a um comportamento totalmente diferente, sem qualquer razão aparente.

Em segundo lugar, busque a otimização, mas somente após o timing e o perfil.Muitos desenvolvedores fazem otimização prematura sem criação de perfil.Na maioria das vezes é completamente inútil.

Outras dicas

Praticamente todas as linguagens fazem uma avaliação de curto-circuito.Significa que a segunda condição só é avaliada se for absolutamente necessária.Para que isso funcione, a maioria das linguagens usa o canal duplo, ||, e não o único, |.

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

Em C, C++ e Java, a instrução:

if (condition1 | condition2) {
  ...
}

avaliará ambas as condições sempre e só será verdadeira se toda a expressão for verdadeira.

A declaração:


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

avaliará condition2 somente se condition1 é falso.A diferença é significativa se condição2 for uma função ou outra expressão com efeito colateral.

Não há, no entanto, nenhuma diferença entre o || caso e o if/else caso.

Tenho visto muitos desses tipos de perguntas ultimamente - otimização ao enésimo grau.

Acho que faz sentido em certas circunstâncias:

  1. A condição de cálculo 2 não é uma operação de tempo constante
  2. Você está perguntando estritamente para fins educacionais - você quer saber como o idioma funciona, não para salvar 3us.

Em outros casos, preocupar-se com a maneira “mais rápida” de iterar ou verificar uma condicional é bobagem.Em vez de escrever testes que exigem milhões de tentativas para ver qualquer diferença registrável (mas insignificante), concentre-se na clareza.

Quando outra pessoa (pode ser você!) pegar esse código em um mês ou um ano, o mais importante será a clareza.

Neste caso, o seu primeiro exemplo é mais curto, mais claro e não exige que você se repita.

De acordo com Este artigo O PHP faz avaliação de curto-circuito, o que significa que se a primeira condição for atendida, a segunda nem será avaliada.Também é muito fácil testar (do artigo):

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

?>

O curto-circuito não é para otimização.Seu objetivo principal é evitar chamar código que não funcionará, mas que resultará em um teste legível.Exemplo:

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

Observe que array[i] pode muito bem obter uma violação de acesso se i estiver fora do alcance e travar o programa.Portanto este programa depende certamente de curto-circuitar a avaliação!

Acredito que esta seja a razão para escrever expressões desta forma com muito mais frequência do que preocupações de otimização.

Embora o uso de curto-circuito para fins de otimização seja muitas vezes um exagero, certamente existem outras razões convincentes para usá-lo.Um exemplo (em C++) é o seguinte:

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

Aqui, o curto-circuito é utilizado para garantir que pObj foi alocado antes de desreferencia-lo.Isso é muito mais conciso do que aninhar if declarações.

Como isso é marcado como independente de idioma, vou intervir.Pelo menos para Perl, a primeira opção é suficiente, não estou familiarizado com PHP.Ele avalia da esquerda para a direita e desaparece assim que a condição é atendida.

Na maioria dos idiomas com otimização decente, o primeiro funcionará perfeitamente.

O | é um operador bit a bit em PHP.Isso não significa $a OR $b, exatamente.Você vai querer usar o tubo duplo.E sim, como mencionado, o PHP faz avaliação de curto-circuito.De maneira semelhante, se a primeira condição de um && cláusula é avaliada como falsa, o PHP também não avalia o restante da cláusula.

VB.net tem duas expressões maravilhosas chamadas "OrElse" e "AndAlso"

OrElse entrará em curto-circuito na primeira vez que atingir uma avaliação True e executará o código desejado.

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

AndAlso entrará em curto-circuito na primeira vez que fizer uma avaliação False e não avaliará o código dentro do bloco.

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

Acho ambos úteis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top