Del lenguaje natural a la expresión C ++

9

Asignación:

Traduzca las siguientes expresiones de lenguaje natural a expresiones C ++. Suponga que todas las variables son números no negativos o booleanos (de valor verdadero o falso).

Lenguaje natural:

O a y b son falsos o c es verdadero, pero no ambos.

Mi solución:

(a==0 && b==0)xor(c==1)

Solución de profesores:

(!a && !b) != c

Preguntas:

  1. Creo que entiendo un poco el primer paréntesis, al decir "no-a" y "no-b" creo que a y b deben estar equivocados, siempre que se suponga que ab no es cero al principio. ¿Derecha?

  2. Pero, ¿qué pasa con la parte que dice "desigual a c"?

  3. No entiendo la solución de los profesores, ¿alguien puede analizarla por mí?

¡Gracias por la ayuda!

limonada
fuente
en general tendría cuidado al traducir expresiones booleanas de lenguaje hablado a código. Un error común es traducir "A es igual a B o C" en a == b or clugar de a == b or a ==c. El problema es que lanuage hablado es imprecisa y, de hecho ambas interpretaciones podría ser válido
IDCLEV 463035818

Respuestas:

5

Asumiré eso a, by lo cson bool.

Dibujemos algunas tablas de verdad:

| a | !a | a==1 | a==0 |
| 0 |  1 |   0  |   1  |
| 1 |  0 |   1  |   0  |

Como se puede ver, ay a==1son equivalentes, y !ay a==0también son equivalentes, por lo que se puede reescribir (a==0 && b==0)xor(c==1)como (!a && !b) xor c.

Ahora algunas tablas de verdad más:

| a | b | a xor b | a != b |
| 0 | 0 |    0    |    0   |
| 0 | 1 |    1    |    1   |
| 1 | 0 |    1    |    1   |
| 1 | 1 |    0    |    0   |

Entonces a!=bes equivalente a a xor b, entonces podemos reescribir (!a && !b) xor cen (!a && !b)!=c. Como puede ver, sus soluciones son totalmente equivalentes, solo escritas con diferentes 'signos'.


UPD : Olvidé mencionarlo. Hay razones por las que la solución del profesor se ve exactamente de esa manera.

La solución del profesor es más idiomática. Si bien su solución es técnicamente correcta, no es un código idiomático de C ++.

El primer pequeño problema es el uso de tipos. Su solución se basa en la conversión entre inty boolcuando compara el valor booleano con un número o uso xor, que es un operador 'exclusivo a nivel de bit' o 'que también actúa sobre ints. En un C ++ moderno, es mucho más apreciado usar valores de tipos correctos y no confiar en tales conversiones, ya que a veces no son tan claras y difíciles de razonar. Para booltales valores son truey en falselugar de 1y 0respectivamente. También !=es más apropiado que xorporque, aunque técnicamente bools se almacenan como números, pero, desde el punto de vista semicográfico, no tiene ningún número, solo valores lógicos.

El segundo problema también se refiere a la idioma. Se encuentra aquí: a == 0. No se considera una buena práctica comparar expresiones booleanas con constantes booleanas. Como ya sabes, a == truees totalmente equivalente a justo a, y a == falsees justo !ao not a(prefiero lo último). Para comprender la razón por la cual esa comparación no es buena, solo compare dos fragmentos de código y decida, lo cual es más claro:

if (str.empty() == false) { ... }

vs

if (not str.empty()) { ... }
Yuri Kovalenko
fuente
1
Si bien es técnicamente correcta, esta respuesta evita por completo hablar sobre tipos y C ++ idiomáticos, que presumiblemente fueron el objetivo de este ejercicio.
Konrad Rudolph el
@KonradRudolph, oh, sí, me olvidé por completo de mencionar eso. Tal vez edite mi respuesta, gracias
Yuri Kovalenko
3

Piensa en booleanos, no en pedacitos

En resumen, la solución de tu profesor es mejor (pero sigue siendo incorrecta, estrictamente hablando, ver más abajo) porque usa operadores booleanos en lugar de operadores bit a bit y trata los booleanos como enteros. La expresión c==1para representar "c es verdadero" es incorrecta porque si c puede ser un número (de acuerdo con la asignación establecida), cualquier valor distinto de cero de c se considerará como representativo true.

Vea esta pregunta sobre por qué es mejor no comparar booleanos con 0 o 1, incluso cuando es seguro hacerlo.

Una muy buena razón para no usar xores que esta es la operación u exclusiva exclusiva en bits . Resulta que funciona en su ejemplo porque tanto el lado izquierdo como el derecho son expresiones booleanas que se convierten a 1 o 0 (ver de nuevo 1 ).

El booleano exclusivo-o es de hecho !=.

Desglosando la expresión

Para comprender mejor la solución de su profesor, es más fácil reemplazar los operadores booleanos con sus equivalentes de "token alternativo", lo que lo convierte en un código C ++ mejor redable (imho) y completamente equivalente: ¡usando 'not' for '!' y 'y' para '&&' obtienes

    (not a and not b) != c

Desafortunadamente, no hay exclusive_orotro operador lógico not_eqque no sea útil en este caso.

Si desglosamos la expresión del lenguaje natural:

O a y b son falsos o c es verdadero, pero no ambos.

primero en una oración sobre proposiciones booleanas A y B:

A o B, pero no ambos.

esto se traduce en A != B(solo para booleanos, no para ningún tipo A y B).

Entonces la proposición A era

ayb son falsos

que se puede indicar como

a es falso y b es falso

que se traduce (not a and not b)y finalmente

c es cierto

Lo que simplemente se traduce en c. Combinándolos obtienes de nuevo (not a and not b) != c.

Para una explicación más detallada de cómo funciona esta expresión, me remito a las tablas de verdad que otros han dado en sus respuestas.

Ambos están equivocados

Y si puedo señalar: la asignación original declaró que a, byc pueden ser números no negativos, pero no indicó inequívocamente que si fueran números, deberían limitarse a los valores 0 y 1. Si hay algún número que sea no 0 representa true, como es habitual, entonces el siguiente código arrojaría una respuesta sorprendente :

    auto c = 2; // "true" in some way
    auto a = 0; // "false"
    auto b = 0; // "false"

    std::cout << ((!a && !b) != c);

// this will output: 1 (!)
// fix by making sure that != compares booleans:

    std::cout << ((!a && !b) != (bool)c);
dhavenith
fuente
Bueno con suerte a, by cse declaran como bool, en cuyo caso c == 1es correcto , aunque es un código atroz. De todos modos, esta es la respuesta que habría escrito: el código de OP puede ser equivalente al del profesor, pero es malo C ++.
Konrad Rudolph el
1
De @KonradRudolph texto asignación de OP: variables are non-negative numbers or boolean. Entonces haga un +1 a @dhavenith de mi parte por captar un detalle que la mayoría de los demás se perdieron (incluido yo, inicialmente).
Frodyne
Genial, Isee. ¡Gracias! Pero, ¿puedes explicarme la solución de mi profesor porque no la entiendo?
Limonade
He agregado una ortografía alternativa para la solución de tu profesor. Esto debería ayudar a aclarar la expresión. Para explicaciones más detalladas, creo que las tablas de verdad en la respuesta de @YuriKovalenko son la mejor manera de abordar la expresión.
dhavenith
2

Trataré de explicar con algunas palabras más: los números se pueden convertir implícitamente en valores booleanos:

El valor cero (para la enumeración integral, de coma flotante y sin ámbito) y el puntero nulo y los valores de puntero nulo a miembro se vuelven falsos. Todos los demás valores se vuelven verdaderos.

Fuente en cppreference

Esto lleva a las siguientes conclusiones:

  • a == 0es lo mismo que !a, porque ase convierte en un booleano y luego se invierte, lo que es igual !(a != 0). Lo mismo vale para b.

  • c==1solo será cierto cuando sea c igual a 1. El uso de la conversión (bool)cproduciría truecuando c != 0no solo si c == 1. Por lo tanto, puede funcionar, porque generalmente se usa el valor 1 para representar true, pero no está garantizado.

  • a != bes lo mismo que a xor bcuando ay bar expresiones booleanas. Es cierto, cuando un valor u otro es cierto, pero no ambos. En este caso, el lado izquierdo (a==0 && b==0)es booleano, por lo que el lado derecho también cse convierte en booleano, por lo tanto, ambos lados se interpretan como expresiones booleanas, por lo tanto, !=es el mismo que xoren este caso.

Puede verificar todo esto usted mismo con las tablas de verdad que proporcionan las otras respuestas.

churill
fuente
2

Como podemos ver en las tablas de verdad:

  • !( not) y ==0dar los mismos resultados.
  • !=y xordar los mismos resultados.
  • c==1 es lo mismo que solo c

Entonces, uno debajo del otro, muestra por qué estas 2 expresiones dan el mismo resultado:

(a==0 && b==0) xor (c==1)
(!a   && !b)   !=   c

Tablas de verdad:

No

    |   | ! |
    | 0 | 1 |
    | 1 | 0 |

== 0

    |   |==0|
    | 0 | 1 |
    | 1 | 0 |

== 1

    |   |==1|
    | 0 | 0 |
    | 1 | 1 |

Y

   | a | b | && |
   | 0 | 0 |  0 |
   | 0 | 1 |  0 |
   | 1 | 0 |  0 |
   | 1 | 1 |  1 |

No es igual

   | a | b | != |
   | 0 | 0 |  0 |
   | 0 | 1 |  1 |
   | 1 | 0 |  1 |
   | 1 | 1 |  0 |

XOR

   | a | b |xor|
   | 0 | 0 | 0 |
   | 0 | 1 | 1 |
   | 1 | 0 | 1 |
   | 1 | 1 | 0 |
Robert Andrzejuk
fuente