Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Algebra di Boole
1
Struttura di un programma C
parte dichiarativa globale
3
Variabili globali e locali
• Le variabili globali sono dichiarate fuori dalle
funzioni
– per convenzione: all’inizio, dopo le #include
• Le variabili locali sono dichiarate internamente
alle funzioni, prima della parte esecutiva
• In caso di programmi monomodulo (cioè
contenenti una sola funzione, il main()), variabili
globali e locali sono equivalenti
– È pertanto indifferente il luogo in cui sono dichiarate
• La differenza si ha nei programmi multimodulo
4
Commenti
• Porzioni di testo racchiuse tra /* e */
– Se un commento si estende da un certo punto fino alla
fine di una sola riga si può anche usare //
/* Programma che non fa nulla ma mostra
i due modi per inserire commenti in C */
int main {
int valore; // Dich. inutile: variabile mai usata
return 0;
}
• I commenti sono ignorati dal compilatore
• Servono per aumentare la leggibilità e la facilità di
modifica di un programma
– A distanza di tempo, per persone diverse dall’autore, ...
5
Istruzioni semplici e composte
(simple and compound statements)
• Sequenze di istruzioni semplici
– Ogni istruzione semplice termina con ;
– ; è detto il “terminatore” dell’istruzione
• Si possono raggruppare più istruzioni in
sequenza tra { e } a costituire un blocco
– Il blocco costituisce una “super-istruzione”
• Non è necessario il ; dopo }, in quanto il
blocco è già una istruzione
– non necessita del terminatore per diventarla
6
Teorema di Böhm e Jacopini
• Tutti i programmi possono essere scritti in
termini di tre strutture di controllo:
– Sequenza: istruzioni eseguite in ordine
– Selezione: istruzioni che permettono di
prendere strade diverse in base a una condizione
(costrutto di tipo if-then-else)
– Iterazione: istruzioni che permettono di
eseguire ripetutamente un certo insieme di altre
istruzioni (costrutti di tipo while, do e for)
7
Sequenza
int main() {
int integer1, integer2, sum;
printf ("Enter first integer\n");
scanf ("%d", &integer1 );
printf ("Enter second integer\n");
scanf ("%d", &integer2);
sum = integer1 + integer2;
printf ("\nSum is %d\n\n", sum );
return 0;
}
8
Selezione
int main()
{
int n;
printf (“Inserisci un numero\n");
scanf ("%d", &n );
if ( n > 0 )
printf ("Un numero positivo ! \n");
else
condizione printf ("Un numero negativo o nullo\n");
printf ("Fine del programma\n");
return 0;
}
9
Iterazione
int main()
{
int n = 9;
printf ( " PRONTI...\n " );
while ( n > 0 ) {
printf (" ...meno %d ...\n", n);
n = n-1;
condizione
}
printf ( " ...VIA!!! \n " );
return 0;
}
10
Iterazione
int main()
{
int n = 9;
printf ( " PRONTI...\n " );
while ( n > 0 )
printf (" ...meno %d ...\n", n);
n = n-1;
condizione
printf ( " ...VIA!!! \n " );
return 0;
}
Che fa?
11
Iterazione
int main()
{
int n = 9;
printf ( " PRONTI...\n " );
while ( n > 0 ) ; {
printf (" ...meno %d ...\n", n);
n = n-1;
condizione
}
printf ( " ...VIA!!! \n " );
return 0;
}
Che fa?
12
Istruzioni condizionali
• L’esecuzione dipende da condizioni sul
valore di espressioni booleane, costruite
mediante operatori:
– Relazionali (predicano sulla relazione tra due valori)
==, !=, <, >, <=, >=
– Logici (predicano sul valore di verità di espressioni logiche)
! (NOT)
&& (AND)
|| (OR)
13
Algebra di Boole
ed
Elementi di Logica
14
Cenni all’algebra di Boole
• L’algebra di Boole (inventata da G. Boole,
britannico, seconda metà ’800), o algebra
della logica, si basa su operazioni logiche
• Le operazioni logiche sono applicabili a
operandi logici, cioè a operandi in grado di
assumere solo i valori vero e falso
• Si può rappresentare vero con il bit 1 e falso
con il bit 0 (convenzione di logica positiva)
15
Operazioni logiche fondamentali
• Operatori logici binari (con 2 operandi logici)
– Operatore OR, o somma logica
– Operatore AND, o prodotto logico
• Operatore logico unario (con 1 operando)
– Operatore NOT, o negazione, o inversione
16
Operatori logici di base
e loro tabelle di verità
A B A or B A B A and B
0 0 0 0 0 0
0 1 1 0 1 0 A not A
1 0 1 1 0 0
1 1 1 1 1 1 0 1
(somma logica) (prodotto logico) 1 0
(negazione)
17
Altri operatori logici
e loro tabelle di verità
A B A xor B A B A xnor B
0 0 0 0 0 1
0 1 1 0 1 0
1 0 1 1 0 0
1 1 0 1 1 1
(o uno o l’altro ma
non entrambi)
18
Espressioni logiche (o Booleane)
• Come le espressioni algebriche, costruite con:
– Variabili logiche (letterali): p. es. A, B, C 0 oppure 1
– Operatori logici: and, or, not
• Esempi:
A or (B and C)
(A and (not B)) or (B and C)
• Precedenza: l’operatore “not” precede l’operatore “and”,
che a sua volta precede l’operatore “or”
A and not B or B and C (A and (not B)) or (B and C)
• Per ricordarlo, si pensi OR come “” (più), AND come “”
(per) e NOT come “” (cambia segno)
19
Tabelle di verità delle espressioni logiche
20
Tabella di verità
di un’espressione logica
A and B or not C
ABC X = A and B Y = not C X or Y
000 0 and 0 = 0 not 0 = 1 0 or 1 =1
001 0 and 0 = 0 not 1 = 0 0 or 0 =0
010 0 and 1 = 0 not 0 = 1 0 or 1 =1
011 0 and 1 = 0 not 1 = 0 0 or 0 =0
100 1 and 0 = 0 not 0 = 1 0 or 1 =1
101 1 and 0 = 0 not 1 = 0 0 or 0 =0
110 1 and 1 = 1 not 0 = 1 1 or 1 =1
111 1 and 1 = 1 not 1 = 0 1 or 0 =1
21
Due esercizi
A B NOT ( ( A OR B) AND ( NOT A ) )
0 0 1 0 0 0 0 1 0
0 1 0 0 1 1 1 1 0
1 0 1 1 1 0 0 0 1
1 1 1 1 1 1 0 0 1
A B C ( B OR NOT C ) AND ( A OR NOT C )
0 0 0 0 1 1 0 1 0 1 1 0
0 0 1 0 0 0 1 0 0 0 0 1
0 1 0 1 1 1 0 1 0 1 1 0
0 1 1 1 1 0 1 0 0 0 0 1
1 0 0 0 1 1 0 1 1 1 1 0
1 0 1 0 0 0 1 0 1 1 0 1
1 1 0 1 1 1 0 1 1 1 1 0
1 1 1 1 1 0 1 1 1 1 0 1
22
A che cosa servono le espressioni logiche?
• A modellare alcune (non tutte) forme di ragionamento
– A è vero che 1 è maggiore di 2 ? (sì o no, qui è no) 0
– B è vero che 2 più 2 fa 4 ? (sì o no, qui è sì) 1
– A and B è vero che 1 sia maggiore di 2 e che 2 più 2 faccia 4 ?
Si ha che A and B 0 and 1 0, dunque no
– A or B è vero che 1 sia maggiore di 2 o che 2 più 2 faccia 4 ?
Si ha che A or B 0 or 1 1, dunque sì
• OR, AND e NOT vengono anche chiamati connettivi logici,
perché funzionano come le congiunzioni coordinanti “o” ed “e”,
e come la negazione “non”, del linguaggio naturale
• Si modellano ragionamenti (o deduzioni) basati solo sull’uso di
“o”, “e” e “non” (non è molto, ma è utile)
23
Che cosa non si può modellare
tramite espressioni logiche?
• Le espressioni logiche (booleane) non modellano:
– Domande esistenziali: “c’è almeno un numero reale x tale
che il suo quadrato valga 1 ?” (si sa bene che non c’è)
x | x2 1 è falso
– Domande universali: “ogni numero naturale è la somma di
quattro quadrati di numeri naturali ?” (si è dimostrato di sì)
x | x a2b2c2d2 è vero (“teorema dei 4 quadrati”)
Più esattamente andrebbe scritto: x a,b,c,d | x a2b2c2d2
• e sono chiamati “operatori di quantificazione”, e
sono ben diversi da or, and e not
• La parte della logica che tratta solo degli operatori or,
and e not si chiama calcolo proposizionale
• Aggiungendo gli operatori di quantificazione, si ha il
calcolo dei predicati (che è molto più complesso)
24
Tautologie e Contraddizioni
• Tautologia
– Una espressione logica che è sempre vera, per
qualunque combinazione di valori delle variabili
• Esempio: principio del “terzo escluso”: A or not A
(tertium non datur, non si dà un terzo caso tra l’evento A
e la sua negazione)
• Contraddizione
– Una espressione logica che è sempre falsa, per
qualunque combinazione di valori delle variabili
• Esempio: principio di “non contraddizione”: A and not A
(l’evento A e la sua negazione non possono essere
entrambi veri)
25
Equivalenza tra espressioni
• Due espressioni logiche si dicono equivalenti (e si
indica con ) se hanno la medesima tabella di
verità. La verifica è algoritmica. Per esempio:
AB not A and not B not (A or B)
00 1 and 1 = 1 not 0 = 1
01 1 and 0 = 0 not 1 = 0
10 0 and 1 = 0 not 1 = 0
11 0 and 0 = 0 not 1 = 0
26
Equivalenza tra espressioni
not ( A and not B or not A and B ) or C and not C
• “C and not C” non contribuisce alla verità dell’espressione con
cui è in disgiunzione.
• Non dipendendo da C, l’espressione si può semplificare ed
esprimere in funzione delle due variabili A e B.
• Risulta essere quindi la definizione dello xnor
( A xnor B = not ( A xor B ) = not( A and not B or B and not A )
A B A xnor B
0 0 1
0 1 0
1 0 0
1 1 1
27
Proprietà dell’algebra di Boole
• L’algebra di Boole gode di svariate proprietà,
formulabili sotto specie di identità
– (cioè formulabili come equivalenze tra espressioni
logiche, valide per qualunque combinazione di
valori delle variabili)
• Esempio celebre: le “Leggi di De Morgan”
not (A and B) not A or not B (1a legge)
not (A or B) not A and not B (2a legge)
28
Ancora sulle proprietà
• Alcune proprietà somigliano a quelle
dell’algebra numerica tradizionale:
– Proprietà associativa: A or (B or C) (A or B) or C (idem per
AND)
– Proprietà commutativa: A or B B or A (idem per AND)
– Proprietà distributiva di AND rispetto a OR:
A and (B or C) A and B or A and C
– … e altre ancora
• Ma parecchie altre sono alquanto insolite…
– Proprietà distributiva di OR rispetto a AND:
A or B and C (A or B) and (A or C)
– Proprietà di assorbimento (A assorbe B):
A or A and B A
– Legge dell’elemento 1: not A or A 1
– … e altre ancora
29
Uso delle proprietà
• Trasformare un’espressione logica in un’altra, differente
per aspetto ma equivalente:
not A and B or A (assorbimento)
= not A and B or (A or A and B) (togli le parentesi)
= not A and B or A or A and B (commutativa)
= not A and B or A and B or A (distributiva)
= (not A or A) and B or A (legge dell’elemento 1)
= true and B or A (vero and B B)
= B or A è più semplice dell’espressione originale !
• Si verifichi l’equivalenza con le tabelle di verità!
• Occorre conoscere un’ampia lista di proprietà e si deve
riuscire a “vederle” nell’espressione (qui è il difficile)
30
Istruzioni condizionali
• L’esecuzione dipende da condizioni sul
valore di espressioni booleane, costruite
mediante operatori:
– Relazionali (predicano sulla relazione tra due valori)
==, !=, <, >, <=, >=
– Logici (predicano sul valore di verità di espressioni logiche)
! (NOT)
&& (AND)
|| (OR)
31
Condizioni: esempi
X == 0
X > 0 && A != 3
!( (x+5)*10 >= ALFA3 / (Beta_Due+1) )
32
Dettagli
• && e || si valutano da sinistra a destra
• La valutazione di una espressione logica
procede finché necessario per dedurne la
verità o falsità, e si arresta appena è definita:
( x != 0 ) && ( (100 / x) == 0 )
33
Vero/falso in C
• Una condizione (espressione relazionale o
logica) assume il valore
0 se risulta FALSA
1 se risulta VERA
• Ogni valore “non zero” è considerato vero
if ( 3 ) ...
if ( -1 ) ...
while (1) ... /* continua PER SEMPRE !! */
if ( a – a ) ... /* sarà sempre FALSO,
indipendentemente dal valore di a */
34
Assegnamento (=) e uguaglianza (==)
• L’istruzione di assegnamento
int a = 0, b = 4;
a = b;
printf( "%d", a );
• Il predicato di confronto
int a = 0, b = 4;
if ( a == b )
printf( "uguali" );
else
printf( "diversi" );
35
Istruzioni condizionali (if-then-else)
• Costrutto a selezione singola:
if ( espressione ) ramo
then
istruzione
oppure a selezione doppia: ramo
if ( espressione ) then
istruzione1 ramo
else else
istruzione2
• I rami possono contenere istruzioni composte:
if ( espressione )
{ seq.1 di istruzioni } sequenze di più
else istruzioni
{ seq.2 di istruzioni }
• Gli if possono essere annidati
36
Istruzione condizionale semplice
if (x < 0) x = -x; else x = x + 10;
Per maggior leggibilità, è bene usare
regole di incolonnamento (indentazione)
if (x < 0)
x = -x;
else è una questione di stile
x = x + 10; ma è molto importante
37
Esempi
if (x < 0)
x = - x; /* trasforma x nel suo valore assoluto */
38
Istruzioni condizionali
(selezione singola)
39
Istruzioni condizionali
(variante con selezione doppia)
40
1 /* Uso delle strutture condizionali,
2 degli operatori relazionali e
3 di uguaglianza */
4 #include <stdio.h>
5
6 int main()
7 {
8 int num1, num2;
9
10 printf ("Enter two integers, and I will tell you\n");
11 printf ("the relationships they satisfy: ");
12 scanf ("%d%d", &num1, &num2); /* lettura di due numeri interi */
13
14 if (num1 == num2)
15 printf ("%d is equal to %d\n", num1, num2);
16
17 if (num1 != num2)
18 printf ("%d is not equal to %d\n", num1, num2);
19
20 if (num1 < num2)
21 printf ("%d is less than %d\n", num1, num2);
22
23 if (num1 > num2)
24 printf ("%d is greater than %d\n", num1, num2);
25
26 if (num1 <= num2)
27 printf ("%d is less than or equal to %d\n",
28 num1, num2);
41
29
30 if (num1 >= num2)
31 printf ("%d is greater than or equal to %d\n",
32 num1, num2);
33
34 return 0; /* il programma è terminato con successo */
35 }
42
if-then-else annidati
if (i < 100)
if (i > 0)
printf ("Minore di 100 e maggiore di zero\n");
else
if (i == 0)
printf("Uguale a zero\n");
else
printf("Minore di zero\n");
else
if (i == 100)
printf( "Uguale a 100\n");
else
printf ("Maggiore di 100\n");
43
Annidamento, blocchi, indentazione
if (n > 0)
Potenziale ambiguità: if (a>b)
z = a;
if (n > 0) if (a>b) z = a; else z = b; else
z = b;
ogni else si associa
all’if più vicino if (n > 0) {
if (a>b)
l'indentazione lo rende evidente
z = a;
se incerti, usare le parentesi }
if (n > 0) { if (a>b) z = a; } else z = b; else
z = b;
44
Sequenze di if
• Spesso accade di voler scrivere molti
if annidati (alternative multiple):
if (...)
fai qualcosa1;
else
if (…)
fai qualcosa2;
else
if(…)
45
if (n % 2 == 0)
Esempio
printf("%d è pari", n);
else
if (n % 3 == 0)
printf("%d è multiplo di 3", n);
else
if (n % 5 == 0)
printf("%d è multiplo di 5", n);
else
if (n % 7 == 0)
printf("%d è multiplo di 7", n);
else
if (n % 11 == 0)
printf("%d è multiplo di 11", n);
else
if (n % 13 == 0)
printf("%d è multiplo di 13", n);
else
printf ("il numero %d non ha divisori primi < 15",
n);
46
Una rappresentazione più leggibile
/* Se un numero n ha divisori primi <15, stampa il minimo,
altrimenti stampa un messaggio che lo segnala */
if (n % 2 == 0)
printf("%d è pari", n);
else if (n % 3 == 0)
printf("%d è multiplo di 3", n);
else if (n % 5 == 0)
printf("%d è multiplo di 5", n);
else if (n % 7 == 0)
printf("%d è multiplo di 7", n);
else if (n % 11 == 0)
printf("%d è multiplo di 11", n);
else if (n % 13 == 0)
printf("%d è multiplo di 13", n);
else printf ("il numero %d non ha divisori primi < 15", n);
47
Cosa cambia?
if (n % 2 == 0) if (n % 2 == 0)
printf("%d è pari", n); printf("%d è pari", n);
else if (n % 3 == 0) if (n % 3 == 0)
printf("%d è multiplo di 3", n); printf("%d è multiplo di 3", n);
else if (n % 5 == 0) if (n % 5 == 0)
printf("%d è multiplo di 5", n); printf("%d è multiplo di 5", n);
else if (n % 7 == 0) if (n % 7 == 0)
printf("%d è multiplo di 7", n); printf("%d è multiplo di 7", n);
else if (n % 11 == 0) if (n % 11 == 0)
printf("%d è multiplo di 11", n); printf("%d è multiplo di 11", n);
else if (n % 13 == 0) if (n % 13 == 0)
printf("%d è multiplo di 13", n); printf("%d è multiplo di 13", n);
48