Logik och kontrollstrukturer Flödet av instruktioner i ett programmeringsspråk bygger vi upp med hjälp av dess kontrollstrukturer. I C har vi exemplen if, if else, while, do while. Dessutom finns switch och?-operatorn som är kompakta former av if else och for-satsen som är en kompakt form av while. Samtliga kontrollstrukturer bygger på att skapa logiska uttryck. Programmering och logik är därför nära kopplade. Veckans övning går ut på att träna i logik. Logiska utsagor och uttryck En utsaga kan vara sann eller falsk, t.ex. Sara kör en bil, värdet på variabeln x är 4. Inom logiken anges en utsaga vanligen med någon av bokstäverna p, q eller r. Utsagorna kan i sin tur kombineras med logiska operatorer för att bilda logiska uttryck som även det kan vara sant eller falskt. De tre vanligaste logiska operatorerna är och (konjunktion), eller (disjunktion) och icke (negation). Ett exempel på ett uttryck är Sara kör en bil och Sara svänger höger Utsagorna är Sara kör en bil (låt oss kalla utsagan för p) och Sara svänger höger (q). Den logiska operatorn är och. Frågan är nu om uttrycket är sant eller falskt. Givetvis beror det dels på om de två utsagorna i sig är sanna eller falska och vad som händer i kombination med operatorn. I detta exempel har vi fyra fall vi måste betrakta. Om Sara kör en bil så är utsagan sann, annars falsk. Samma med Sara svänger höger. Det blir fyra fall då det finns fyra möjliga kombinationer. För att uttrycket ska vara sant krävs att båda utsagorna är sanna, annars blir utsagan falsk och detta beror på operatorn och. Blir det alltid så? Ja faktiskt. Vad händer om vi ändrar operatorn till eller? Vi reder strax ut detta. Operator och betecknas i logiken med och inom programmering i C med &&. Eller betecknas med respektive och icke med ~(eller respektive!. Låt oss nu ta några exempel på uttryck och hur de representeras. uttryck Sara kör en bil och Sara svänger höger Sara svänger inte höger Sara svänger höger men kör inte bil logik p q q q p För att avgöra om uttrycken blir sanna eller falska behöver vi först reda ut hur operatorerna fungerar. Vi bygger en sanningstabell. Vi skriver T för true (sann) och F för false (falskt). p q ~p (icke p) p q (p och q) p q (p eller q) T T F T T T F F (q är irrelevant) F T F T T F T F F T (q är irrelevant) F F
Av tabellen ovan ser vi svaret på frågan vi ställde tidigare. Uttrycket Sara kör bil eller Sara svänger höger blir sant om minst en av utsagorna är sann. Enda gången det är falskt är om båda utsagorna är falska. Sara kanske inte svänger alls och hon sitter på en cykel. Däremot blir det sant om Sara sitter på en cykel och svänger höger. Av exemplen ovan har vi rett ut de två första, men vad händer i sista exemplet. Sara svänger höger men kör inte bil. Återigen tar vi en sanningstabell. p q p q p T T F F T F F F F T T T F F T F Föga förvånande så ser vi av tabellen att enda gången uttrycket är sant är när p är falskt (Sara kör inte bil) och när q är sant, dvs att Sara svänger höger. Prioritetsordning Prioritet är viktigt inom såväl matematik som programmering. Vad blir uttrycket 1 + 6 2? 14 eller 13? Vad görs först, addition eller multiplikation? Från matematiken vet vi att vi alltid ska utföra multiplikation före addition. Uttrycket blir alltså 13. Inom programmering kallas detta för prioritetsordning för operatorer. Även i C utförs alltså multiplikation före addition. Hur är det då i logiken? ~ före och före Behövs en annan prioritet behöver vi använda parenteser (1+6) 2 (p q) r Uppgift 1 Bestäm två utsagor som du kan använda i samtliga fall nedan. Formulera sedan logiska uttryck för de sju fallen. Skriv en sanningstabell för 3 och 6. 1. Det brinner inte. 2. Det brinner och ryker. 3. Det ryker, men brinner inte. 4. Det varken ryker eller brinner. 5. Det brinner inte och det ryker inte heller. 6. Det brinner inte fast det ryker. 7. Det brinner!
Uppgift 2 Två variabler p och q är deklarerade som heltal men lagrar ett logiskt värde (1 eller 0) där variabeln antas vara sann om värdet är 1 och falsk om värdet är 0. Variabeln p ska ha värdet 1 om det brinner, annars värdet 0. Variabeln q ska ha värdet 1 om det ryker annars värdet 0. Skriv de satser i C som krävs så att variablerna har ett korrekt värde om tillstånden i de sju meningarna ovan råder. Implikation En logisk sats som är intressant är implikation, som på begriplig svenska kan uttryckas som om-så. Inom logiken uttrycks det med operatorn. Om vi har uttrycket p q, så betyder det att om p är sant så ska q vara sant. Ett exempel. Om det regnar så blir det blött. Kolla in sanningstabellen för detta uttryck och se om du håller med. p q p q T T T T F F F T T F F T Observera att uttrycket blir sant i båda fallen där p är falskt. I vårt fall innebär det att uttrycket om det regnar så blir det blött blir sant i de fall det inte regnar, vilket först kan verka konstigt, men det är rätt logiskt. Det kan faktiskt både vara torrt och blött om det inte regnar, men av andra orsaker. Om det regnar kan uttrycket däremot bara bli sant om det också blir blött. På engelska blir översättningen av om-så (alltså implikation), if-else. Tada! Uppgift 3 Formulera logiska uttryck för de fem fallen nedan. Skriv en sanningstabell för 8 och 10. 8. Om det ryker, så brinner det. 9. Det brinner om det ryker. 10. Det ryker inte, om det inte brinner. 11. Det brinner endast om det ryker (svår fundera på sanningstabell). 12. Om det brinner brinner det. Uppgift 4 Fortsätt nu från uppgift 2 och skriv de satser i C som krävs så att variablerna har ett korrekt värde om tillstånden i de fem meningarna ovan råder. Observera alltså att du kan använda if-else. Uppgift 5 Låt oss ha följande utsagor p = "Solen skiner", q = "Det regnar" och r = "Det är rötmånad". Nu har vi representerat dem som tre logiska uttryck i C. Översätt dem till svenska så gott det går och försök formulera det så som vi skulle göra i vardagligt tal. 1. (q && p) r 2. p q && r
3. p &&!q r Uppgift 6 Appropå prioritetsordning, avskaffa så många parentespar som det går i följande uttryck. 1. ((p (!q)) && r) 2. ((!((p && q) && (p)) (!(p)) && r)) 3.!(p ((q && p) ((p) (p q)))) Ekvivalens Det är enkelt. Om två uttryck ger samma sanningstabell, så är de ekvivalenta. Det innebär att de är utbytbara. Att finna enklare men logiskt ekvivalenta uttryck är mycket viktigt i programmering. Många fel i mjukvara uppstår pga av logiska misstag av den som programmerar. Det beror ofta på att man har alltför komplicerade uttryck. Att förenkla logiska uttryck underlättar därför både programmering och felsökning av program. Tre vanliga ekvivalenta uttryck som ofta används vid förenkling är följande p q) ~p q p q) ~p q p q p ~q Uppgift 7 Detta är en mer avancerad uppgift. Förenkla följande satser och verifiera ditt svar med en sanningstabell. 1. p p && q 2. (p q) (p && q) 3. ((p q) (r!r)) Uppgift 8 Vad skrivs ut? int i = i + 1; for (i=0; i<5; i=i+1)