Zadanie:
Przetłumacz następujące wyrażenia języka naturalnego na wyrażenia C ++. Załóżmy, że wszystkie zmienne są liczbami nieujemnymi lub wartością logiczną (o wartości true lub false).
Język naturalny:
Albo a i b są fałszywe, lub c jest prawdą, ale nie jedno i drugie.
Moje rozwiązanie:
(a==0 && b==0)xor(c==1)
Rozwiązanie dla profesorów:
(!a && !b) != c
Pytania:
Myślę, że lekko rozumiem pierwszą nawias, mówiąc „nie-a” i „nie-b”. Myślę, że aib muszą być wtedy błędne, pod warunkiem, że ab na początku przyjmuje się, że nie jest zero. Dobrze?
Ale co z częścią, która mówi „nierówne do c”?
Nie rozumiem rozwiązania dla profesorów, czy ktoś może to dla mnie rozbić?
Dziękuję za pomoc!
a == b or c
zamiasta == b or a ==c
. Problem polega na tym, że mówiony język jest nieprecyzyjny i faktycznie obie interpretacje mogą być poprawneOdpowiedzi:
Będę zakładać, że
a
,b
ic
sąbool
.Narysujmy kilka tabel prawdy:
Jak widać
a
ia==1
są równoważne,!a
ia==0
są również równoważne, więc możemy przepisać(a==0 && b==0)xor(c==1)
jako(!a && !b) xor c
.Teraz jeszcze kilka tabel prawdy:
Więc
a!=b
jest równoważnea xor b
, więc możemy przepisać(!a && !b) xor c
do(!a && !b)!=c
. Jak widzisz, twoje rozwiązania są w pełni równoważne, tylko napisane różnymi „znakami”.UPD : Zapomniałem wspomnieć. Istnieją powody, dla których rozwiązanie profesora wygląda dokładnie w ten sposób.
Rozwiązanie profesora jest bardziej idiotyczne. Chociaż Twoje rozwiązanie jest technicznie poprawne, nie jest to idiomatyczny kod C ++.
Pierwszym małym problemem jest użycie typów. Twoje rozwiązanie opiera się na konwersji pomiędzy
int
ibool
podczas porównywania wartości logicznej z liczbą lub zastosowaniemxor
, co jest „wyłącznym bitem” lub operatorem działającym również naint
s. W nowoczesnym języku C ++ o wiele bardziej doceniane jest stosowanie wartości poprawnych typów i nie poleganie na takich konwersjach, ponieważ czasami nie są one tak jasne i trudne do uzasadnienia. Dlabool
takich wartości sątrue
ifalse
zamiast1
i0
odpowiednio.!=
Jest to również bardziej odpowiednie niż to,xor
że chociaż techniczniebool
s są przechowywane jako liczby, ale sematycznie nie masz żadnych liczb, tylko wartości logiczne.Drugi problem dotyczy także idiomii. Leży tutaj:
a == 0
. Porównywanie wyrażeń boolowskich ze stałymi boolowskimi nie jest uważane za dobrą praktykę. Jak już wiesz,a == true
jest w pełni równoważny z justa
ia == false
jest sprawiedliwy!a
lubnot a
(wolę ten drugi). Aby zrozumieć powód, dla którego to porównanie nie jest dobre, po prostu porównaj dwa fragmenty kodu i zdecyduj, co jest jaśniejsze:vs
źródło
Myśl booleany, a nie bity
Podsumowując, rozwiązanie twojego profesora jest lepsze (ale nadal błędne, ściśle mówiąc, patrz dalej w dół), ponieważ używa operatorów logicznych zamiast operatorów bitowych i traktuje logiczne jako liczby całkowite. Wyrażenie
c==1
reprezentujące „c jest prawdą” jest niepoprawne, ponieważ jeśli c może być liczbą (zgodnie z podanym przypisaniem), wówczas każdą niezerową wartość c należy traktować jako reprezentującątrue
.Zobacz pytanie, dlaczego lepiej nie porównywać boolanów z 0 lub 1, nawet jeśli jest to bezpieczne.
Jednym z bardzo dobrych powodów, aby nie używać,
xor
jest to, że jest to nieco wykluczająca operacja. Zdarza się, że działa w twoim przykładzie, ponieważ zarówno lewa strona, jak i prawa strona są wyrażeniami logicznymi, które są konwertowane na 1 lub 0 (zobacz ponownie 1 ).Wartość logiczna wyłączna - lub w rzeczywistości jest
!=
.Podział wyrazu
Aby lepiej zrozumieć rozwiązanie twojego profesora, najłatwiej jest zastąpić operatory logiczne ich ekwiwalentami „alternatywnego tokena”, co czyni go lepszym do redable (imho) i całkowicie równoważnym kodem C ++: Używanie „nie” dla ”!” oraz „i” za „&&”
Niestety nie ma innego
exclusive_or
operatora logicznego niżnot_eq
, co w tym przypadku nie jest pomocne.Jeśli rozbimy naturalne wyrażenie językowe:
najpierw do zdania o zdaniach boolowskich A i B:
przekłada się to na
A != B
(tylko dla booleanów, nie dla żadnego typu A i B).Wtedy była twierdzenie A.
które można określić jako
co przekłada się na
(not a and not b)
i wreszcieCo po prostu przekłada się na
c
. Łącząc je otrzymujesz ponownie(not a and not b) != c
.W celu dalszego wyjaśnienia, jak to wyrażenie działa, odsyłam do tabel prawdy, które inni podali w swoich odpowiedziach.
Oboje się mylicie
I jeśli mogę wytropić: Pierwotny przydział stwierdził, że a, b i c mogą być liczbami nieujemnymi, ale nie stwierdził jednoznacznie, że jeśli byłyby liczbami, powinny być ograniczone do wartości 0 i 1. Jeśli dowolna liczba, która jest nie 0 oznacza
true
, jak zwykle, następujący kod dałby zaskakującą odpowiedź :źródło
a
, żeb
ic
są zadeklarowane jakobool
, w którymc == 1
to przypadku jest poprawny , choć okropny kod. W każdym razie jest to odpowiedź, którą napisałbym: kod OP może być równoważny kodowi profesora, ale jest to zły C ++.variables are non-negative numbers or boolean
. Od +1 do @dhavenith ode mnie za uchwycenie szczegółów, których większość innych tutaj tęskniło (w tym mnie początkowo).Spróbuję wyjaśnić jeszcze kilkoma słowami: Liczby można domyślnie przekonwertować na wartości logiczne:
Źródło na temat preferencji
Prowadzi to do następujących wniosków:
a == 0
jest taki sam jak!a
, ponieważa
jest konwertowany na wartość logiczną, a następnie odwrócony, co jest równe!(a != 0)
. To samo dotyczy b.c==1
stanie się prawdą tylko wtedy, gdy będziec
równa 1. Użycie konwersji(bool)c
dałoby wynik,true
gdyc != 0
nie tylko, jeślic == 1
. Może więc działać, ponieważ zwykle używa się wartości 1 do reprezentowaniatrue
, ale nie jest ona gwarantowana.a != b
jest taka sama jaka xor b
podczasa
ib
ar wyrażeń logicznych. To prawda, gdy jedna lub druga wartość jest prawdziwa, ale nie obie. W tym przypadku lewa strona(a==0 && b==0)
jest wartością logiczną, więc prawa strona równieżc
jest konwertowana na wartość logiczną, więc obie strony są interpretowane jako wyrażenia boolowskie, a zatem!=
są takie same jakxor
w tym przypadku.Możesz to wszystko sprawdzić samodzielnie z tabelami prawdy, które podały inne odpowiedzi.
źródło
Jak widać z tabel prawdy:
!
(not
) i==0
dać te same wyniki.!=
ixor
dać te same wyniki.c==1
jest taki sam jak sprawiedliwyc
Tak więc jedno pod drugim pokazuje, dlaczego te 2 wyrażenia dają ten sam wynik:
Tabele prawdy:
Nie
== 0
== 1
I
Nie równe
XOR
źródło