Pregunta

He separados a cabo una prueba para determinar si dos elementos de programación se superponen debido a la ilegibilidad de la misma.

¿Hay alguna aplicación para ayudar en la simplificación de una declaración lógica?

Ejemplo: (originalmente un ejemplo defectuoso, pero expone razones por las que solicita esta)

if (x < y && y < z && x < z)  

podría reducirse a

if (x < y && y < z)

Mi código es:

return (shift.Start <= shift2.Start && shift.End >= shift2.End) || (shift2.Start <= shift.Start && shift2.End >= shift.Start)

Me encantaría hacer esa simple, y creo que es posible, simplemente no está seguro cómo.

En vista de que este es realmente el lenguaje agnóstico, incluso convertir a un guión diferente para encontrar posibilidades sería bueno, sin necesidad de que sea en C #, por ejemplo.

¿Fue útil?

Solución

Cuando se trata de sentencias lógicas complejas, usted es generalmente mejor con el formato de su código de manera legible que intentar alguna optimización prematura (raíz de todo mal, etc.)

Por ejemplo:

return (shift.Start <= shift2.Start && shift.End >= shift2.End) || (shift2.Start <= shift.StartTime && shift2.End >= shift.Start)

Puede, para facilitar la lectura y facilidad de mantenimiento, ser reprogramado a:

bool bRetVal = false;
bRetVal = (    (   (shift.Start <= shift2.Start)
                && (shift.End >= shift2.End))
            || (   (shift2.Start <= shift.StartTime)
                && (shift2.End >= shift.Start)))
return bRetVal;

La mayoría de los lugares mantienen un estándar de codificación que define algo como lo anterior para grandes bloques lógicos. Prefiero mantener un par de líneas adicionales de código que puede ser leído y entendido que una monstruosidad una línea.

Otros consejos

Matar a la lógica duplicado y podrás matar dos pájaros de un tiro. Usted obtendrá SECO, y obtendrá un nombre de función (comentario del rico):

class Shift:
  def encompasses(other_shift)
    self.start <= other_shift.start && self.end >= other_shift.end

...

return shift1.encompasses(shift2) || shift2.encompasses(shift1)

Tenga mucho, mucho cuidado con este tipo de cambios. Podrían parecer sencillo a simple vista inicial, y la lógica booleana (y las leyes de DeMorgan) no son demasiado difícil de entender, pero hay trampas potenciales a menudo cuando nos fijamos en los casos individuales:

  

Por ejemplo: si (x

Esto no es correcto, si (x < z), y aún podría ser mayor que z. Ese estado no sería pasar sus pruebas originales.

A pesar de x < y && y < z implica x < z (y se definieron como, por ejemplo, Integer y = null, a continuación, la antigua incluso puede causar una NPE en Java, o desconocido en SQL.

  

¿Hay alguna aplicación para ayudar en la simplificación de una declaración lógica?

No he visto a nadie hacer frente a esta parte de la pregunta, así que voy a tomar una puñalada y ver lo que ocurre discusión.

Hay técnicas para trabajar con lógica booleana. En mis días de la universidad (bSEE) se utilizó Karnaugh mapas . Básicamente, se puede tomar una tabla de verdad arbitraria muy complejo y determinar una expresión lógica correcta y optimizada. Utilizamos esto para reducir el número de puertas lógicas en un circuito, que es análoga a la simplificación de una declaración if complejo.

Pros:

  • Puede implementar / optimizar una tabla de verdad muy compleja y arbitraria con relativa facilidad.

Contras:

  • La lógica resultante generalmente tenía poco parecido con la intención de la tabla de verdad. Como otros han sugerido, esto es "ilegible".
  • Un cambio a una sola celda de la tabla de verdad a menudo se traduciría en un completamente expresión diferente. Un simple cambio en el diseño se convierte en una re-escritura, por lo que es imposible de mantener.
  • No-optimizado lógica es mucho más barato que lo que solía ser, mientras que los costes de diseño son los mismos.

En última instancia, lo más crítico es la corrección de la expresión de tabla de verdad / lógica. significa un error de su programa no funcionará bien. No hay ninguna aplicación o diseño de técnica le ayudará si usted no entiende correctamente la definición de la lógica que debe ser implementado.

En mi opinión, algunos problemas del mundo real son lo suficientemente complejas para beneficiarse realmente de este tipo de técnica, pero sí que existe.

Es necesario tener mucho cuidado al hacer esto ... el ejemplo que dio, por ejemplo, simplemente no es cierto ... si x = 1, y = 2, z = 2, entonces x

A veces se puede envolver declaraciones como

shift.Start <= shift2.Start && shift.End> = shift2.End

En una función booleana para que sea más fácil de leer como:

Función ShiftWithinValidRange (nombre terrible aquí, pero se entiende la idea)
{
  Return (shift.Start <= shift2.Start && shift.End> = shift2.End);
}

Si se asume de inicio y Hora de inicio se supone realmente ser el mismo campo, su condición se reduce a

(a <= b && c >= d) || (b <= a && d >= c)

Podemos convertir esto en

(a <= b && d <= c) || (b <= a && c <= d)

pero esto todavía no se ve como se simplifica mucho.

Esto no sólo es peligroso, sino que a menudo conduce a la más difícil de mantener código. La lógica booleana es más fácil de entender cuando se desglosa en pasos específicos. Condensación de la lógica a menudo conducen a la más difícil de entender la lógica.

es decir. en su ejemplo, ¿por qué estamos comprobando si x < z, cuando lo que realmente queremos saber es x < y && y < z?

La solución más sencilla es a menudo la mejor. Condensar su lógica en código 'más frío', pero menos legible no es bueno en el largo plazo.

No tengo una solución general para ti, pero si uso la sintaxis Lisp se parece mucho más simple para mí:

(and (< x y)
     (< y z)
     (< x z))

A continuación, darse cuenta de que las dos primeras cláusulas:

(and (< x y)
     (< y z))

se pueden combinar en:

(and (< x y z))

Así que la expresión completa ahora se ve así:

(and (< x y z)
     (< x z))

Ahora es obvio que la segunda es redundante, por lo que es a:

(and (< x y z))

o simplemente:

(< x y z)

que en C-sintaxis es:

(x < y && y < z)

Creo que la respuesta de Wayne Conrad es el más adecuado, pero para fines de entretenimiento, esto es otra forma de decir que (creo):

(long) shift.Start.CompareTo(shift2.Start) * (long) shift.End.CompareTo(shift2.End) <= 0

Es esto realmente más rápido? No lo sé. Es ciertamente más difícil de leer.

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