Dal linguaggio naturale all'espressione C ++


9

Incarico:

Traduci le seguenti espressioni in linguaggio naturale in espressioni C ++. Supponiamo che tutte le variabili siano numeri non negativi o booleani (di valore vero o falso).

Linguaggio naturale:

O aeb sono entrambi falsi oppure c è vero, ma non entrambi.

La mia soluzione:

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

Soluzione per i professori:

(!a && !b) != c

Domande:

  1. Penso di comprendere leggermente la prima parentesi, dicendo "non-a" e "non-b" Penso che aeb debbano quindi essere sbagliati, a condizione che all'inizio si supponga che non sia zero. Giusto?

  2. Ma per quanto riguarda la parte che dice "disuguale a c"?

  3. Non capisco la soluzione dei professori, qualcuno può romperlo per me?

Grazie per l'aiuto!


in generale starei attento a tradurre espressioni booleane di lingua parlata in codice. Un errore comune è tradurre "A è uguale a B o C" a == b or canziché a == b or a ==c. Il problema è che il linguaggio parlato è impreciso e in realtà entrambe le interpretazioni potrebbero essere valide
idclev 463035818

Risposte:


5

Darò per scontato che a, be csono bool.

Disegniamo alcune tabelle di verità:

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

Come si può vedere, ae a==1sono equivalenti, e !aed a==0è anche equivalente, in modo che possiamo riscrivere (a==0 && b==0)xor(c==1)come (!a && !b) xor c.

Ora alcune altre tabelle di verità:

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

Quindi, a!=bè equivalente a a xor b, in modo che possiamo riscrivere (!a && !b) xor ca (!a && !b)!=c. Come vedi, le tue soluzioni sono completamente equivalenti, scritte solo con diversi "segni".


UPD : Ho dimenticato di menzionare. Ci sono ragioni per cui la soluzione del professore appare esattamente in quel modo.

La soluzione del professore è più idiomatica. Sebbene la tua soluzione sia tecnicamente corretta, non è un codice C ++ idiomatico.

Il primo piccolo problema è l'uso dei tipi. La tua soluzione si basa sulla conversione tra inte boolquando confronti il ​​valore booleano con un numero o un uso xor, che è un "bit-saggio esclusivo" o un operatore che agisce anche su ints. In un moderno C ++ è molto più apprezzato usare valori di tipi corretti e non fare affidamento su conversioni di questo tipo, a volte non così chiare e difficili da ragionare. Per booltali valori sono truee falseinvece di 1e 0rispettivamente. Inoltre !=è più appropriato rispetto al xorfatto che mentre tecnicamente i bools sono memorizzati come numeri, ma semestralmente non hai numeri, solo valori logici.

Il secondo numero riguarda anche l'idioma. Si trova qui: a == 0. Non è considerata una buona pratica confrontare espressioni booleane con costanti booleane. Come già sapete, a == trueè del tutto equivalente a just a, ed a == falseè giusto !ao not a(preferisco quest'ultimo). Per capire il motivo per cui quel confronto non è buono, confronta due frammenti di codice e decidi, che è più chiaro:

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

vs

if (not str.empty()) { ... }

1
Sebbene tecnicamente corretta, questa risposta evita completamente di parlare di tipi e di C ++ idiomatico, che erano presumibilmente il punto di questo esercizio.
Konrad Rudolph,

@KonradRudolph, oh, sì, ho completamente dimenticato di menzionarlo. Forse modificherò la mia risposta, grazie
Yuri Kovalenko il

3

Pensa ai booleani, non ai bit

In sintesi, la soluzione del tuo professore è migliore (ma è ancora sbagliata, a rigor di termini, vedi più in basso) perché utilizza operatori booleani invece di operatori bit a bit e tratta i valori booleani come numeri interi. L'espressione c==1per rappresentare "c è vera" non è corretta perché se c può essere un numero (secondo l'assegnazione dichiarata), qualsiasi valore diverso da zero di c deve essere considerato rappresentativo true.

Vedi questa domanda sul perché è meglio non confrontare i valori booleani con 0 o 1, anche quando è sicuro farlo.

Un ottimo motivo per non usare xorè che si tratta dell'esclusiva o dell'operazione bit-saggia . Succede nel tuo esempio perché sia ​​il lato sinistro che il lato destro sono espressioni booleane che vengono convertite in 1 o 0 (vedi di nuovo 1 ).

L'esclusiva booleana, o in effetti lo è !=.

Abbattere l'espressione

Per comprendere meglio la soluzione del tuo professore, è più semplice sostituire gli operatori booleani con i loro equivalenti "token alternativi", che lo trasformano in un codice C ++ redable (imho) e completamente equivalente: usando 'not' for '!' e 'e' per '&&' ottieni

    (not a and not b) != c

Sfortunatamente, non esiste un exclusive_oroperatore logico diverso da quello not_eq, il che non è utile in questo caso.

Se suddividiamo l'espressione del linguaggio naturale:

O aeb sono entrambi falsi oppure c è vero, ma non entrambi.

prima in una frase sulle proposizioni booleane A e B:

A o B, ma non entrambi.

questo si traduce in A != B(solo per i booleani, non per qualsiasi tipo A e B).

Quindi la proposizione A fu

aeb sono entrambi falsi

che può essere dichiarato come

a è falso e b è falso

che si traduce in (not a and not b), e infine

c è vero

Che si traduce semplicemente in c. Combinandoli si ottiene di nuovo (not a and not b) != c.

Per ulteriori spiegazioni su come funziona questa espressione, rimando alle tabelle di verità che altri hanno fornito nelle loro risposte.

Sbagli entrambi

E se potessi puntualizzare: l'assegnazione originale affermava che a, bec possono essere numeri non negativi, ma non affermava in modo inequivocabile che se fossero numeri, dovrebbero essere limitati ai valori 0 e 1. Se qualsiasi numero che è non 0 rappresenta true, come è consuetudine, quindi il seguente codice darebbe una risposta 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);

Beh a, si spera , be csono dichiarati come bool, nel qual caso c == 1è corretto , anche se codice atroce. Comunque, questa è la risposta che avrei scritto: il codice di OP potrebbe essere equivalente a quello del professore, ma è un C ++ negativo.
Konrad Rudolph,

1
@KonradRudolph Dal testo assegnazione di OP: variables are non-negative numbers or boolean. Quindi +1 a @dhavenith da parte mia per aver catturato un dettaglio che la maggior parte degli altri qui ha perso (incluso me, inizialmente).
Frodyne,

Ottimo, Isee. Grazie! Ma puoi spiegarmi la soluzione del mio professore perché non la capisco.
limonade,

Ho aggiunto un'ortografia alternativa per la soluzione del tuo professore. Ciò dovrebbe aiutare a chiarire l'espressione. Per spiegazioni più dettagliate, penso che le tabelle di verità nella risposta di @YuriKovalenko siano il modo migliore per avvicinarsi all'espressione.
Dhavenith,

2

Proverò a spiegare con qualche altra parola: i numeri possono essere implicitamente convertiti in valori booleani:

Il valore zero (per l'enumerazione integrale, in virgola mobile e senza ambito) e il puntatore null e i valori null puntatore-membro diventano falsi. Tutti gli altri valori diventano veri.

Fonte su cppreference

Ciò porta alle seguenti conclusioni:

  • a == 0è lo stesso di !a, perché aviene convertito in un valore booleano e quindi invertito, che equivale a !(a != 0). Lo stesso vale per b.

  • c==1diventerà vero solo quando è c uguale a 1. L'uso della conversione (bool)cprodurrebbe truequando c != 0non solo se c == 1. Quindi può funzionare, perché di solito si utilizza il valore 1 per rappresentare true, ma non è garantito.

  • a != bè lo stesso di a xor bquando ae le bespressioni booleane. È vero, quando un valore o l'altro è vero, ma non entrambi. In questo caso il lato sinistro (a==0 && b==0)è booleano, quindi anche il lato destro cviene convertito in booleano, quindi entrambi i lati vengono interpretati come espressioni booleane, quindi !=è lo stesso xordi questo caso.

Puoi controllare tutto questo da solo con le verità fornite dalle altre risposte.


2

Come possiamo vedere dalle tabelle di verità:

  • !( not) e ==0dare gli stessi risultati.
  • !=e xordare gli stessi risultati.
  • c==1 è lo stesso di solo c

Quindi uno sotto l'altro, mostra perché queste 2 espressioni danno lo stesso risultato:

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

Tabelle della verità:

Non

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

== 0

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

== 1

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

E

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

Non uguale

   | 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 |
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.