Pregunta

Tengo una declaración if con dos condiciones (separadas por un operador OR), una de las condiciones cubre más del 70% de las situaciones y tarda mucho menos tiempo en procesarse/ejecutarse que la segunda condición, por lo que, en aras de la velocidad, solo quiero la segunda condición que se procesará si la primera condición se evalúa como falsa.

Si ordeno las condiciones para que la primera condición (la más rápida) aparezca primero en la declaración if, en las ocasiones en las que esta condición se cumple y se evalúa como verdadera, ¿se procesa siquiera la segunda condición?

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

¿O necesitaría anidar dos declaraciones if para verificar solo la segunda condición si la primera se evalúa como falsa?

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

Estoy trabajando en PHP, sin embargo, supongo que esto puede ser independiente del idioma.

¿Fue útil?

Solución

Para C, C++, C#, Java y otros lenguajes .NET, las expresiones booleanas se optimizan para que, tan pronto como se sepa lo suficiente, no se evalúe nada más.

Un viejo truco para crear código ofuscado era usar esto para crear declaraciones if, como por ejemplo:

a || b();

Si "a" es verdadera, "b()" nunca se evaluará, por lo que podemos reescribirla en:

if(!a)
    b();

y de manera similar:

a && b();

se convertiría

if(a)
    b();

tenga en cuenta que esto solo es válido para el || y && operador.Los dos operadores | y y es bit a bit o y, y, respectivamente, y por lo tanto no están "optimizados".

EDITAR:Como mencionaron otros, intentar optimizar el código utilizando la lógica de cortocircuito rara vez es un tiempo bien invertido.

Primero busque claridad, tanto porque es más fácil de leer como de comprender.Además, si intentas ser demasiado inteligente, una simple reordenación de los términos podría llevar a un comportamiento tremendamente diferente sin ninguna razón aparente.

En segundo lugar, opte por la optimización, pero sólo después de cronometrar y crear perfiles.Demasiados desarrolladores realizan optimizaciones prematuras sin crear perfiles.La mayoría de las veces es completamente inútil.

Otros consejos

Casi todos los idiomas realizan una evaluación de cortocircuito.Lo que significa que la segunda condición solo se evalúa si es absolutamente necesario.Para que esto funcione, la mayoría de los lenguajes usan la tubería doble, ||, no la única, |.

Ver http://en.wikipedia.org/wiki/Short-circuit_evaluación

En C, C++ y Java, la declaración:

if (condition1 | condition2) {
  ...
}

evaluará ambas condiciones cada vez y solo será verdadera si toda la expresión es verdadera.

La declaración:


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

evaluará condition2 sólo si condition1 Es falso.La diferencia es significativa si condición2 es una función u otra expresión con un efecto secundario.

No hay, sin embargo, ninguna diferencia entre el || caso y el if/else caso.

He visto muchos de este tipo de preguntas últimamente: optimización al enésimo grado.

Creo que tiene sentido en determinadas circunstancias:

  1. La condición de cálculo 2 no es una operación de tiempo constante
  2. Estás preguntando estrictamente con fines educativos: quieres saber cómo funciona el idioma, no para salvarnos.

En otros casos, preocuparse por la forma "más rápida" de iterar o comprobar un condicional es una tontería.En lugar de escribir pruebas que requieren millones de pruebas para ver cualquier diferencia registrable (pero insignificante), céntrese en la claridad.

Cuando alguien más (¡podrías ser tú!) recoja este código en un mes o un año, lo más importante será la claridad.

En este caso, su primer ejemplo es más breve, más claro y no requiere que lo repita.

De acuerdo a Este artículo PHP realiza una evaluación de cortocircuito, lo que significa que si se cumple la primera condición, la segunda ni siquiera se evalúa.También es bastante fácil de probar (del artículo):

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

?>

El cortocircuito no es para optimización.Su objetivo principal es evitar llamar a código que no funcionará, pero que dará como resultado una prueba legible.Ejemplo:

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

Tenga en cuenta que es muy posible que array[i] sufra una infracción de acceso si i está fuera de rango y bloquea el programa.¡Por lo tanto, este programa depende ciertamente de cortocircuitar la evaluación!

Creo que esta es la razón por la que se escriben expresiones de esta manera con mucha más frecuencia que por cuestiones de optimización.

Si bien el uso de cortocircuitos con fines de optimización suele ser excesivo, ciertamente existen otras razones de peso para usarlo.Un ejemplo de ello (en C++) es el siguiente:

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

Aquí, se confía en el cortocircuito para garantizar que pObj ha sido asignado antes de desreferenciarlo.Esto es mucho más conciso que haber anidado if declaraciones.

Dado que esto está etiquetado como independiente del idioma, intervendré.Al menos para Perl, la primera opción es suficiente, no estoy familiarizado con PHP.Se evalúa de izquierda a derecha y se abandona tan pronto como se cumple la condición.

En la mayoría de los lenguajes con una optimización decente, el primero funcionará bien.

El | es un operador bit a bit en PHP.No significa $a OR $b, exactamente.Querrás usar el tubo doble.Y sí, como se mencionó, PHP realiza una evaluación de cortocircuito.De manera similar, si la primera condición de un && La cláusula se evalúa como falsa, PHP tampoco evalúa el resto de la cláusula.

VB.net tiene dos expresiones maravillosas llamadas "OrElse" y "AndAlso"

De lo contrario, se producirá un cortocircuito la primera vez que alcance una evaluación verdadera y ejecutará el código que desee.

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

Y también se producirá un cortocircuito la primera vez que realice una evaluación falsa y no evaluará el código dentro del bloque.

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

Ambos me parecen útiles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top