Semantyka i weryfikacja programów/Ćwiczenia 2: Różnice pomiędzy wersjami

Z Studia Informatyczne
Przejdź do nawigacjiPrzejdź do wyszukiwania
Sl (dyskusja | edycje)
Nie podano opisu zmian
Sl (dyskusja | edycje)
Nie podano opisu zmian
Linia 190: Linia 190:
Takie rozwiązanie nie jest zatem ''czystą'' semantyką
Takie rozwiązanie nie jest zatem ''czystą'' semantyką
małych kroków.
małych kroków.
Istnieją inne możliwe rozwiązania, w stylu małych kroków,
Istnieją inne możliwe rozwiązania w stylu małych kroków.
np. przy użyciu rozszerzonej składni.
Jedno z nich oparte jest na pomyśle, aby ''rozwinąc'' pętlę
Znalezienie takiego rozwiązania pozostawiamy dociekliwemu czytelnikowi.
<math> \mathbf{while}\, </math> jeden raz:
 
<math>
\mathbf{while}\, b \,\mathbf{do}\, I, s \,\Longrightarrow\, \mathbf{if}\, b \,\mathbf{then}\, (I; \mathbf{while}\, b \,\mathbf{do}\, I) \,\mathbf{else}\, \mathbf{skip}, s.
</math>
 
Dzięki temu obliczany warunek logiczny <math> b </math> jest zawsze
''jednorazowy''.
Znalezienie innych rozwiązań, np. opartych na rozszerzeniu składni,
pozostawiamy dociekliwemu czytelnikowi.


Reguły dla operacji arytmetycznych pozostawiamy do napisania Czytelnikowi.
Reguły dla operacji arytmetycznych pozostawiamy do napisania Czytelnikowi.
Linia 204: Linia 213:
I \, ::= \,\,
I \, ::= \,\,
         \mathbf{repeat}\, I \,\mathbf{until}\, b  \,\,|\,\,
         \mathbf{repeat}\, I \,\mathbf{until}\, b  \,\,|\,\,
         \mathbf{FOR}\, x := e_1 \,\mathbf{to}\, e_2 \,\mathbf{do}\, I  \,\,|\,\,
         \mathbf{for}\, x := e_1 \,\mathbf{to}\, e_2 \,\mathbf{do}\, I  \,\,|\,\,
         \,\mathbf{do}\, I e \,\mathbf{times}  \,\,|\,\,
         \,\mathbf{do}\, I e \, \,\mathbf{times}  \,\,|\,\,
         \,\mathbf{do}\, I \,\mathbf{while}\, b  
         \,\mathbf{do}\, I \,\mathbf{while}\, b  
</math>
</math>


Napisz semantykę małych kroków dla powyższych konstrukcji.
Napisz semantykę małych kroków dla powyższych konstrukcji.
Niedozwolone jest korzystanie z jakiejś konstrukcji w semantyce
innej, np.


<math>
 
\,\mathbf{do}\, I \,\mathbf{while}\, b \,\Longrightarrow\, \mathbf{repeat}\, I \,\mathbf{until}\, \neg b
 
==== Rozwiązanie ====
 
 
Zacznijmy od pętli <math> \mathbf{repeat}\, I \,\mathbf{until}\, b </math>.
Przyjrzyjmy się dwóm podejściom, które zastosowaliśmy dla
pętli <math> \mathbf{while}\, </math> w poprzednim zadaniu.
Po pierwsze rozwinięcie:
 
<math>
\mathbf{repeat}\, I \,\mathbf{until}\, b, s \,\Longrightarrow\, I; \mathbf{if}\, b \,\mathbf{then}\, (\mathbf{repeat}\, I \,\mathbf{until}\, b) \,\mathbf{else}\, \mathbf{skip}, s.
</math>
 
Po drugie, spróbujmy odwołać się do <math> \,\Longrightarrow\,^{*} </math> dla dozoru pętli
<math> b </math>:
 
<math>
\frac{I, s \,\Longrightarrow\, I', s'}
    {\mathbf{repeat}\, I \,\mathbf{until}\, b, s \,\Longrightarrow\, \mathbf{repeat}\, I' \,\mathbf{until}\, b, s'}
</math>
 
<math>
\frac{I, s \,\Longrightarrow\, s' \quad b, s \,\Longrightarrow\,^{*} \mathbf{true}}
    {\mathbf{repeat}\, I \,\mathbf{until}\, b, s \,\Longrightarrow\, s'}
\quad \quad
\frac{I, s \,\Longrightarrow\, s' \quad b, s \,\Longrightarrow\,^{*} \mathbf{true}}
    {\mathbf{repeat}\, I \,\mathbf{until}\, b, s \,\Longrightarrow\, \mathbf{repeat}\, ? \,\mathbf{until}\, b, s'}
</math>
</math>


Okazuje się, że jest jeszcze gorzej niż w przypadku pętli <math> \mathbf{while}\, </math>:
nie pamiętamy już, jaka była instrukcja wewnętrzna naszej pętli!


==== Rozwiązanie ====




.....
.....


Semantykę dla <math> \,\mathbf{do}\, I \mathbf{while}\, b </math> pozostawiamy Czytelnikowi jako
ćwiczenie.
Oczywiście minimalistyczne rozwiązanie to
<math>
\,\mathbf{do}\, I \,\mathbf{while}\, b, s \,\Longrightarrow\, \mathbf{repeat}\, I \,\mathbf{until}\, \neg b, s
</math>




Linia 252: Linia 295:
pisemnego:
pisemnego:


<math>
<math>
e_1 0 + e_2 0 \,\Longrightarrow\, (e_1 + e_2) 0
e_1 0 + e_2 0 \,\Longrightarrow\, (e_1 + e_2) 0
</math>
</math>


<math>
<math>
e_1 0 + e_2 1 \,\Longrightarrow\, (e_1 + e_2) 1
e_1 0 + e_2 1 \,\Longrightarrow\, (e_1 + e_2) 1
</math>
</math>


<math>
<math>
e_1 1 + e_2 0 \,\Longrightarrow\, (e_1 + e_2) 1
e_1 1 + e_2 0 \,\Longrightarrow\, (e_1 + e_2) 1
</math>
</math>
Linia 266: Linia 309:
Ale co zrobić z przeniesieniem?  
Ale co zrobić z przeniesieniem?  


<math>
<math>
e_1 1 + e_2 1 \,\Longrightarrow\, ?
e_1 1 + e_2 1 \,\Longrightarrow\, ?
</math>
</math>
Linia 272: Linia 315:
Podstawowy pomysł polega na potraktowaniu przeniesienia jak dodatkowego składnika:
Podstawowy pomysł polega na potraktowaniu przeniesienia jak dodatkowego składnika:


<math>
<math>
e_1 1 + e_2 1 \,\Longrightarrow\, ((e_1 + e_2) + \epsilon 1) 0
e_1 1 + e_2 1 \,\Longrightarrow\, ((e_1 + e_2) + \epsilon 1) 0
</math>
</math>
Linia 302: Linia 345:
Gdy jeden ze składników ma mniej cyfr niż drugi, potrzebujemy reguł:
Gdy jeden ze składników ma mniej cyfr niż drugi, potrzebujemy reguł:


<math>
<math>
\epsilon + e 0 \,\Longrightarrow\, e 0
\epsilon + e 0 \,\Longrightarrow\, e 0
\quad \quad
\quad \quad
Linia 310: Linia 353:
oraz ich odpowiedników:
oraz ich odpowiedników:


<math>
<math>
e 0 + \epsilon \,\Longrightarrow\, e 0
e 0 + \epsilon \,\Longrightarrow\, e 0
\quad \quad
\quad \quad
Linia 318: Linia 361:
Niestety, nie możemy użyć reguły przemienności:
Niestety, nie możemy użyć reguły przemienności:


<math>
<math>
e_1 + e_2 \,\Longrightarrow\, e_2 + e_1
e_1 + e_2 \,\Longrightarrow\, e_2 + e_1
</math>
</math>


gdyż spowodowałaby ona możliwość ''pętlenia się'', a zatem braku wyniku obliczania wyrażenie.
gdyż spowodowałaby ona możliwość ''pętlenia się'', a zatem braku wyniku obliczenia.


Na koniec dodajemy typowe reguły opisujące jak krok podwyrażenia daje
Na koniec dodajemy typowe reguły opisujące jak krok podwyrażenia indukuje
krok całęgo wyrażenia:
krok całego wyrażenia:


<math>
<math>
\frac{e_1 \,\Longrightarrow\, e'_1}
\frac{e_1 \,\Longrightarrow\, e'_1}
     {e_1 + e_2 \,\Longrightarrow\, e'_1 + e_2}
     {e_1 + e_2 \,\Longrightarrow\, e'_1 + e_2}
Linia 364: Linia 407:
Napisz semantykę operacyjną obliczającą wyrażenie wraz z
Napisz semantykę operacyjną obliczającą wyrażenie wraz z
informacja o ewentualnym przepełnieniu.
informacja o ewentualnym przepełnieniu.
Wynik powinien byc poprawny przynajmniej dal wyrażeń w składni
Wynik powinien byc poprawny przynajmniej dla wyrażeń w składni
ograniczonej.
ograniczonej.


Linia 385: Linia 428:
cyfr, i to ten właśnie składnik odnotował przepełnienie:
cyfr, i to ten właśnie składnik odnotował przepełnienie:


<math>
<math>
p + e 0 \,\Longrightarrow\, e 0
p + e 0 \,\Longrightarrow\, e 0
\quad \quad
\quad \quad
Linia 392: Linia 435:
e 0 + p \,\Longrightarrow\, e 0
e 0 + p \,\Longrightarrow\, e 0
\quad \quad
\quad \quad
e 1 + p \,\Longrightarrow\, e 1
e 1 + p \,\Longrightarrow\, e 1.
</math>
</math>


Linia 400: Linia 443:
cyfr, to reguły  
cyfr, to reguły  


<math>
<math>
\epsilon + e 0 \,\Longrightarrow\, e 0
\epsilon + e 0 \,\Longrightarrow\, e 0
\quad \quad
\quad \quad
Linia 417: Linia 460:
powinna zostać zachowana:
powinna zostać zachowana:


<math>
<math>
p + p \,\Longrightarrow\, p
p + p \,\Longrightarrow\, p.
</math>
</math>


Linia 427: Linia 470:
Oto odpowiednie reguły:
Oto odpowiednie reguły:


<math>
<math>
p + \epsilon \,\Longrightarrow\, \epsilon
p + \epsilon \,\Longrightarrow\, \epsilon
\quad \quad
\quad \quad
\epsilon + p \,\Longrightarrow\, \epsilon
\epsilon + p \,\Longrightarrow\, \epsilon.
</math>
</math>


Linia 442: Linia 485:
Odpowiednia reguła to
Odpowiednia reguła to


<math>
<math>
e_1 1 + e_2 1 \,\Longrightarrow\, ((e_1 + e_2) + p 1) 0.
e_1 1 + e_2 1 \,\Longrightarrow\, ((e_1 + e_2) + p 1) 0.
</math>
</math>

Wersja z 19:06, 27 lip 2006


Zawartość

Ćwiczymy dalej semantykę małych kroków. Uzupełnimy semantykę języka Tiny o semantykę operacyjną wyrażeń boolowskich i arytmetycznych. Następnie rozszerzymy nasz język o róznorodne konstrukcje iteracji. Na koniec zdefiniujemy operacje arytmetyczne liczb binarnych.


Rozszerzenia języka Tiny

Zadanie 1

Semantyka języka Tiny z wykładu używała funkcji semantycznych B,E:StateState dla określenie znaczenia wyrażeń boolowskich i arytmetycznych. Zdefiniuj znaczenie wyrażeń za pomocą semantyki operacyjnej, w stylu małych kroków.

Rozwiązanie

Przypomnijmy składnię wyrażeń boolowskich i arytmetycznych:

b::=true|false|e1e2|¬b|b1b2|

e::=0|1||x|e1+e2|

Chcemy, aby tranzycje dla wyrażeń były postaci: e,se,s i podobnie dla wyrażeń boolowskich: b,sb,s gdzie sState.


Zacznijmy od wyrażeń boolowskich.

true,struefalse,sfalse

Przejdźmy do spójników logicznych, powiedzmy b1b2. Ponieważ opisujemy teraz pojedyncze (małe) kroki składające się na wykonanie programu, musimy podać w jakiej kolejności będą się obliczać b1 i b2. Zacznijmy od strategii lewostronnej:

b1,sb'1,sb1b2,sb'1b2,sb2,sb'2,sl1b2,sl1b2,sl1l2l, o ile l=l1l2

Możemy zaniechać obliczania b2 jeśli b1 oblicza się do false. Oto odpowiednio zmodyfikowane reguły:

b1,sb'1,sb1b2,sb'1b2,sfalseb2,sfalsetrueb2,sb2,s

Analogicznie reguły prawostronne to:

b2,sb'2,sb1b2,sb1b'2,sb1false,sfalseb1true,sb1,s

Reguły równoległe otrzymujemy jako sumę reguł lewo- i prawostronnych (w sumie 6 reguł). Zauważmy, że obliczanie wyrażeń b1 i b2 odbywa się teraz w twz. przeplocie: Pojedynczy krok polega na wykonaniu jednego kroku obliczenia b1 albo jednego kroku obliczenia b2. Zwróćmy też uwagę, że nasze tranzycje nie posiadają teraz własności determinizmu: wyrażenie b1b2 może wyewoluować w pojedyńczym kroku albo do b'1b2 albo do b1b'2. Na szczęście, końcowy wynik, do jakiego oblicza się wyrażenie jest zawsze taki sam, niezależnie od przeplotu.

Oto reguła dla negacji:

¬true,sfalse,s¬false,strue,sb,sb,s¬b,s¬b,s

Reguły dla e1e2 są następujące:

e1,se'1,se1e2,se'1e2,se2,se'2,se1e2,se1e'2,sn1n2,strue,s o ile n1n2n1n2,sfalse,s o ile n1>n2

Reguły powyższe zależą od semantyki wyrażen arytmetycznych. Zauważmy, że ponownie pozostawiliśmy dowolność jeśli chodzi o kolejność obliczania wyrażeń arytmetycznych e_1 i e_2.

Rozważmy teraz instrukcję warunkową i instrukcję pętli. Najpierw obliczamy wartość dozoru:

b,sb,s𝐢𝐟b𝐭𝐡𝐞𝐧I1𝐞𝐥𝐬𝐞I2,s𝐢𝐟b𝐭𝐡𝐞𝐧I1𝐞𝐥𝐬𝐞I2,sb,sb,s𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I,s𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I,s

a gdy dozór jest już obliczony, podejmujemy decyzję. W przypadku instrukcji warunkowej reguły są oczywiste:

𝐢𝐟true𝐭𝐡𝐞𝐧I1𝐞𝐥𝐬𝐞I2,sI1,s𝐢𝐟false𝐭𝐡𝐞𝐧I1𝐞𝐥𝐬𝐞I2,sI2,s

Gorzej jest w przypadku instukcji pętli. Reguła mogłaby wyglądać tak:

𝐰𝐡𝐢𝐥𝐞true𝐝𝐨I,sI;𝐰𝐡𝐢𝐥𝐞?𝐝𝐨I,s

ale nie wiemy już, jaki był dozór pętli (widzimy tylko wynik obliczenia tego dozoru w stanie s, czyli 𝐭𝐫𝐮𝐞). Możemy odwołać się do tranzytywnego domknięcia relacji (czyli w zadadzie do semantyki dużych kroków):

b,s*true𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I,sI;𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I,sb,s*false𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I,ss

Takie rozwiązanie nie jest zatem czystą semantyką małych kroków. Istnieją inne możliwe rozwiązania w stylu małych kroków. Jedno z nich oparte jest na pomyśle, aby rozwinąc pętlę 𝐰𝐡𝐢𝐥𝐞 jeden raz:

𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I,s𝐢𝐟b𝐭𝐡𝐞𝐧(I;𝐰𝐡𝐢𝐥𝐞b𝐝𝐨I)𝐞𝐥𝐬𝐞𝐬𝐤𝐢𝐩,s.

Dzięki temu obliczany warunek logiczny b jest zawsze jednorazowy. Znalezienie innych rozwiązań, np. opartych na rozszerzeniu składni, pozostawiamy dociekliwemu czytelnikowi.

Reguły dla operacji arytmetycznych pozostawiamy do napisania Czytelnikowi.


Zadanie 2

Rozszerzmy język Tiny o następujące dobrze znane konstrukcje iteracji:

I::=𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b|𝐟𝐨𝐫x:=e1𝐭𝐨e2𝐝𝐨I|𝐝𝐨Ie𝐭𝐢𝐦𝐞𝐬|𝐝𝐨I𝐰𝐡𝐢𝐥𝐞b

Napisz semantykę małych kroków dla powyższych konstrukcji.


Rozwiązanie

Zacznijmy od pętli 𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b. Przyjrzyjmy się dwóm podejściom, które zastosowaliśmy dla pętli 𝐰𝐡𝐢𝐥𝐞 w poprzednim zadaniu. Po pierwsze rozwinięcie:

𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b,sI;𝐢𝐟b𝐭𝐡𝐞𝐧(𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b)𝐞𝐥𝐬𝐞𝐬𝐤𝐢𝐩,s.

Po drugie, spróbujmy odwołać się do * dla dozoru pętli b:

I,sI,s𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b,s𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b,s
I,ssb,s*𝐭𝐫𝐮𝐞𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b,ssI,ssb,s*𝐭𝐫𝐮𝐞𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥b,s𝐫𝐞𝐩𝐞𝐚𝐭?𝐮𝐧𝐭𝐢𝐥b,s

Okazuje się, że jest jeszcze gorzej niż w przypadku pętli 𝐰𝐡𝐢𝐥𝐞: nie pamiętamy już, jaka była instrukcja wewnętrzna naszej pętli!


.....


Semantykę dla 𝐝𝐨I𝐰𝐡𝐢𝐥𝐞b pozostawiamy Czytelnikowi jako ćwiczenie. Oczywiście minimalistyczne rozwiązanie to

𝐝𝐨I𝐰𝐡𝐢𝐥𝐞b,s𝐫𝐞𝐩𝐞𝐚𝐭I𝐮𝐧𝐭𝐢𝐥¬b,s


Kalkulator binarny

Zadanie 1

Rozważmy następujący język wyrażeń (liczby binarne z dodawaniem):

e::=ϵ|e0|e1|e1+e2

ϵ oznacza słowo puste, czyli np. ϵ101 oznacza binarną liczbę 101. Napisz semantykę operacyjną obliczającą wartość wyrażeń.


Rozwiązanie

Składnia wyrażeń pozwala na wygodny dostęp do najmniej znaczącego bitu liczby. Spróbujmy zatem zastosować metodę dodawania pisemnego:

e10+e20(e1+e2)0
e10+e21(e1+e2)1
e11+e20(e1+e2)1

Ale co zrobić z przeniesieniem?

e11+e21?

Podstawowy pomysł polega na potraktowaniu przeniesienia jak dodatkowego składnika:

e11+e21((e1+e2)+ϵ1)0

Zauważmy, że w składni dopuszcza się dowolne przeplatanie operatora dodawania i bitów 0,1. Tę dowolność wykorzystaliśmy właśnie w regułach powyżej. Gdyby nasz język ograniczyć tylko do składni

e::=b|e1+e2

b::=ϵ|b0|b1

(nazwijmy ją składnią ograniczoną) to powyższe reguły byłyby niepoprawne.

Zanim dopiszemy pozostałe reguły, określmy zbiór konfiguracji jako zbiór wyrażeń. Konfiguracje końcowe to wyrażenia bez operatora dodawania (liczby binarne). Nasz pomysł jest taki, że tranzycje stopniowo przesuwają operator dodawania w lewo, aż się go ostatecznie pozbędą.

Gdy jeden ze składników ma mniej cyfr niż drugi, potrzebujemy reguł:

ϵ+e0e0ϵ+e1e1

oraz ich odpowiedników:

e0+ϵe0e1+ϵe1.

Niestety, nie możemy użyć reguły przemienności:

e1+e2e2+e1

gdyż spowodowałaby ona możliwość pętlenia się, a zatem braku wyniku obliczenia.

Na koniec dodajemy typowe reguły opisujące jak krok podwyrażenia indukuje krok całego wyrażenia:

e1e'1e1+e2e'1+e2e2e'2e1+e2e1+e'2eee0e0eee1e1


Zadanie 2

Rozszerzmy składnię o jeden symbol p oznaczający przepełnienie: e::=ϵ|p|e0|e1|e1+e2 Na przykład p101 oznacza tę samą liczbę co ϵ101, ale z dodatkową informacją, że podczas jej obliczania nastąpiło przepełnienie. Rozumiemy przez to sytuację, gdy wynik ma więcej cyfr niż każdy z argumentów. Cyfry zero z lewej strony (najbardziej znaczące) również uważamy za pełnoprawne cyfry, nie należy ich usuwać ani dodawać nowych.

Napisz semantykę operacyjną obliczającą wyrażenie wraz z informacja o ewentualnym przepełnieniu. Wynik powinien byc poprawny przynajmniej dla wyrażeń w składni ograniczonej.

Rozwiązanie

Zadanie dotyczy w zasadzie składni ograniczonej, ale jako konfiguracji pośrednich będziemy zapewne potrzebować wyrażeń wykraczających poza tę składnię, np. (e1+e2)0, podobnie jak w poprzednim zadaniu. Zatem mamy tu do czynienia z typowym zabiegiem rozszerzania składni na użytek semantyki operacyjnej (z tym, że rozszerzenie jest dane z góry i nie musimy go wymyślać :)

Przyjmijmy, że konfiguracjami są dowolne wyrażenia, a konfiguracjami końcowymi wyrażenia bez operatora dodawania (ale teraz mogą to być np. wyrażenia postaci p100). Spróbujmy pozostawić wszystkie reguły z poprzedniego zadania. Dodamy tylko kilka nowych reguł, odpowiedzialnych za przepełnienie.

Zacznijmy od najprostszej sytuacji, gdy jeden ze składników ma mniej cyfr, i to ten właśnie składnik odnotował przepełnienie:

p+e0e0p+e1e1e0+pe0e1+pe1.

W takiej sytuacji oczywiście informacja o przepełnieniu zostaje wymazana. Jeśli przepełnienie zostało odnotowane w składniku o większej liczbie cyfr, to reguły

ϵ+e0e0ϵ+e1e1e0+ϵe0e1+ϵe1.

z poprzedniego zadania są wystarczające.

Rozważmy teraz przypadek, gdy obydwa składniki mają tę samą liczbę cyfr. Jeśli obydwa odnotowały przepełnienie, to oczywiście informacja ta powinna zostać zachowana:

p+pp.

Ale co należy zrobić, gdy tylko jeden ze składników odnotował przepełnienie? p+ϵ? Oczywiście, w tej sytuacji żadnego przepełnienia nie ma, ponieważ drugi składnik ma wystarczająco dużo cyfr by je przesłonić. Oto odpowiednie reguły:

p+ϵϵϵ+pϵ.

Na koniec zostało najważniejsze: kiedy powinniśmy generować sygnał o przepełnieniu? Przypomnijmy sobie reguły dla dadawania pisemnego w poprzednim zadaniu. Jeśli nie ma przeniesienia, to przepełnienie nie może powstać. Natomiast jeśli jest przeniesienie, to stanowi ono potencjalne przepełnienie. Odpowiednia reguła to

e11+e21((e1+e2)+p1)0.

Nowy sztuczny składnik p1 zawiera jakby na wszelki wypadek informacje o potencjalnym przepełnieniu. Jeśli którykolwiek z pozostałych składników e1 i e2 ma przynajmniej jedną cyfrę, to p zostanie usunięte. W przeciwnym wypadku symbol p i przetrwa i będzie poprawnie informował o sytuacji przepełnienia.


Zadania domowe

Zadanie 1

Podaj przykład wyrażenia, które nie policzy się ani przy użyciu strategii lewo- ani prawostronnej, a policzy się przy strategii równoległej.


Zadanie 2

Dodaj do wyrażeń binarnych operację odejmowania.