FUNZIONI BOOLEANE
Le funzioni booleane prendono il nome da Boole, che introdusse un formalismo che opera su variabili (dette
variabili booleane o variabili logiche o asserzioni) che possono assumere due soli valori:


Vero
Falso
Tale formalismo è detto algebra booleana e nasce come tentativo di definire in forma algebrica processi di
tipo logico-deduttivo. Tuttavia, poiché di fatto l’algebra di Boole opera su variabili binarie, che possono cioè
assumere solo due valori, è possibile definire una corrispondenza fra i valori logici vero e falso e i valori
binari 0 e 1, includendo di fatto gli operatori booleani fra gli operatori dell’algebra binaria. Al valore vero
viene normalmente fatto corrispondere il valore binario 1, mentre al valore falso viene fatto corrispondere il
valore binario 0.
L’algebra booleana è definita su un insieme finito di valori (i due valori vero e falso) che è possibile
manipolare attraverso funzioni opportunamente definite. Tali funzioni operano su una o due variabili
booleane e producono come risultato un solo valore, anch’esso booleano.
Gli operatori di base, con cui è possibile costruire qualunque altra funzione di variabili booleane, sono 3:



NOT
AND
OR
(opera su una sola variabile booleana; il risultato è la negazione della variabile)
(opera su due variabili booleane; il risultato è vero se entrambe le variabili hanno valore vero)
(opera su due variabili booleane; il risultato è vero se almeno una variabile ha valore vero)
In realtà è possibile dimostrare che qualunque funzione booleana può essere rappresentata utilizzando solo 2
di questi operatori, di cui uno sia NOT.
Operatori e funzioni booleane possono essere descritte attraverso le cosiddette tabelle di verità, che
associano a ciascuna possibile combinazione di valori delle variabili il corrispondente valore della funzione.
Le tabelle di verità per NOT, AND e OR sono le seguenti:
X
NOT X
X1
X2
X1 AND X2
X1
X2
X1 OR X2
0
1
0
0
0
0
0
0
1
0
0
1
0
0
1
1
1
0
0
1
0
1
1
1
1
1
1
1
Si può notare come la tabella di verità di una funzione ad N variabili abbia N+1 colonne, una per ogni
variabile di ingresso più una per il valore che deve assumere la funzione. Inoltre, una tabella di verità ha
tante righe quante sono le combinazioni possibili che le variabili di ingresso possono realizzare. Poiché i
valori assunti da ciascuna variabile sono soltanto 2, con N variabili si avranno 2N possibili combinazioni.
Quindi una funzione booleana di N variabili potrà essere rappresentata da una tabella di verità costituita da
N+1 colonne e 2N righe. Pertanto l’operatore NOT, che opera su una singola variabile, ha una tabella di
verità costituita da 2 righe e 2 colonne, mentre le tabelle di verità relative agli operatori AND e OR, che
operano su 2 variabili booleane, sono costituite da 4 righe e 3 colonne.
Un’altra considerazione che si può fare è relativa al numero di funzioni che possono essere ottenute a partire
da un certo numero di variabili. Poiché ogni riga (corrispondente ad una possibile combinazione delle
variabili di ingresso) potrà presentare due possibili valori nella colonna relativa al valore che la funzione
assume in corrispondenza di tale combinazione, il numero di combinazioni possibili dei valori di uscita (e
quindi di funzioni diverse che si possono generare) sarà 2 elevato al numero delle righe, che abbiamo detto
1
essere 2N, quindi 22N. (Per analogia, nel Totocalcio, in cui si hanno 3 possibili risultati per ognuna delle 13
partite, il numero di possibili combinazioni vincenti è 313).
Pertanto, ad esempio, si possono generare 4 diverse funzioni di una sola variabile X, in cui l’uscita:
1.
2.
3.
4.
è uno in entrambi i casi (X=0 e X=1)
è zero in entrambi i casi
è uguale al valore assunto dalla variabile di ingresso (funzione identità)
è la negazione della variabile di ingresso (funzione NOT)
Nel caso di 2 variabili avremo invece 16 possibili funzioni, fra cui sono particolarmente importanti la
funzione XOR (OR esclusivo, il valore dell’uscita è vero se o l’una o l’altra delle variabili di ingresso, ma
non entrambe, hanno valore vero) e le funzioni NAND e NOR che sono la negazione di AND e OR, cioè i
cui valori sono la negazione dei valori assunti da AND e OR in corrispondenza delle omologhe
configurazioni delle variabili di ingresso.
X1
X2
X1 XOR X2
0
0
0
1
0
1
0
1
1
1
1
0
X1
X2
X1 NAND X2
X1
X2
X1 NOR X2
0
0
1
0
0
1
0
1
1
0
1
0
1
0
1
1
0
0
1
1
0
1
1
0
Come si può vedere, poiché i valori che le variabili e le funzioni possono assumere sono solo 2, è molto
facile che funzioni ottenute mediante combinazioni diverse di operatori forniscano gli stessi risultati. Del
resto, è stato detto che tutte le funzioni booleane possono essere espresse utilizzando la coppia di operatori
NOT e AND, oppure la coppia NOT e OR.
Per verificare che due funzioni booleane siano equivalenti, come ad esempio che X1 NAND X2 equivale a
NOT (X1 AND X2), basterà quindi verificare che le loro tabelle di verità siano uguali, che cioè facciano
corrispondere lo stesso valore a uguali combinazioni delle variabili su cui sono definite.
INTERPRETAZIONE LOGICA DEGLI OPERATORI
Come già detto, il primo obiettivo con cui è stata definita l’algebra booleana è quello di rappresentare
operazioni logiche in forma di operazioni algebriche. Da questo punto di vista, è possibile identificare le
variabili di ingresso delle funzioni booleane come rappresentazioni di fatti o di asserzioni.
Ad esempio, se si tratta di figure geometriche e si associa alla variabile X1 l’informazione “ha 3 lati”, alla
variabile X2 l’informazione “tutti i lati sono uguali”, alla variabile A1 il concetto “è un triangolo” e alla
variabile A2 il concetto “è un triangolo equilatero” si potranno determinare le seguenti relazioni:
A1 = X1
A2 = X1 AND X2
2
In questo caso il simbolo = rappresenta la relazione logica di equivalenza, quindi le espressioni precedenti
vanno lette come “una figura geometrica è un triangolo se e solo se ha 3 lati” e “una figura geometrica è un
triangolo equilatero se e solo se ha tre lati e tutti i lati sono uguali” .
In modo analogo espressioni logiche possono esprimere criteri che devono essere soddisfatti, ad esempio
quando si ricercano informazioni in una base di dati o con un motore di ricerca su Internet. In quest’ultimo
caso, l’interfaccia utente permette di solito (esplicitamente o implicitamente) di esprimere criteri di ricerca
sotto forma di funzioni booleane, le cui variabili sono le parole che le pagine Web che si stanno cercando
devono contenere: se la parola è presente nella pagina, allora la corrispondente variabile assumerà il valore
vero. I siti elencati saranno tutti quelli per cui l’espressione booleana che viene usata come criterio di
selezione ha come valore vero. Quindi, se si cercano le pagine che contengono informazioni su cavalli o
cani (e non necessariamente su entrambi) si potrà usare come criterio “cavalli OR cani”. Se invece si cercano
informazioni sui cavalli, ma si vogliono evitare le pagine in cui si parla di cavalli come unità di misura di
potenza dei motori, si potrà adottare il criterio “cavalli AND NOT motore”.
Un altro esempio pratico: se cerchiamo una ricetta per una macedonia di frutta e utilizziamo “macedonia”
come criterio di ricerca
otteniamo anche (e soprattutto) risultati che riguardano la Macedonia intesa come regione balcanica. Occorre
quindi restringere la ricerca, utilizzando un criterio più articolato, ad es. “macedonia AND frutta”.
3
OPERATORI BOOLEANI E CALCOLATORI
Dal momento che gli operatori booleani possono essere assimilati in ogni caso a funzioni di variabili binarie,
non solo vengono inclusi nel set di istruzioni delle CPU, ma tutti i circuiti digitali (reti logiche) che
costituiscono l’hardware di un calcolatore sono composti da un elevato numero di circuiti elementari (porte
logiche) che realizzano gli operatori logici di base (NOT, AND, OR, NAND, NOR, XOR). Quindi la
progettazione di una rete logica, dalle più semplici fino ai microprocessori, che sono sicuramente le più
complesse, può essere “ridotta” alla ricerca della funzione logica che produce le uscite desiderate in presenza
di certi ingressi. Tuttavia, come si è detto, ci sono molti modi per ottenere la stessa funzione booleana
utilizzando diverse combinazioni di operatori logici elementari. Quindi la soluzione ottima per il progetto
sarà quella che non solo rispetta le specifiche del progetto (cioè realizza correttamente la funzione
desiderata), ma che riesce anche a farlo utilizzando il minor numero di porte logiche. Infatti un circuito più
semplice è più economico e anche più veloce nell’eseguire l’operazione per cui è stato progettato.
Infatti, da un lato, le onde elettromagnetiche, e quindi i segnali che vengono elaborati all’interno di un
calcolatore, si propagano ad una velocità prossima a quella della luce, che è elevatissima ma comunque
finita. Pertanto abbreviare il percorso che i segnali devono “attraversare” per compiere una certa operazione
comporta una riduzione del tempo di esecuzione. Dall’altro lato, si deve tenere presente che, ogni volta che
si attiva una porta logica, i circuiti che la compongono richiedono un tempo significativo (anche se è molto
piccolo, tipicamente inferiore a 10-6 / 10-9 secondi, è comunque molto maggiore del tempo di propagazione
del segnale lungo un conduttore di lunghezza paragonabile) per raggiungere una configurazione stabile che
consente di “leggerne” il risultato correttamente. Per questo motivo, ridurre il numero di porte logiche
comporta una riduzione del tempo richiesto per eseguire l’operazione che queste realizzano.
A livello di operazioni eseguite dalla CPU, si è visto come i dati su cui queste vengono eseguite siano
normalmente raggruppati in byte o in multipli di un byte. Tuttavia abbiamo visto che gli operatori booleani
operano su singoli bit. Quindi, come si può interpretare l’istruzione A AND B, dove A e B sono, ad esempio,
due parole da 8 bit ? Il risultato dell’applicazione di un operatore booleano a parole di più bit non è altro che
una parola della stessa lunghezza in cui ciascun bit rappresenta il risultato dell’operatore applicato ai due bit
che si trovano in posizioni corrispondenti nei due operandi.
Es.
A = 11100110
B = 01011101
A AND B = 01000100
A OR B = 111111111
A
B
A AND B
11100110
01011101
01000100
(ogni bit è il risultato dell’AND fra i due bit corrispondenti degli operandi)
A OR B
11111111
(ogni bit è il risultato dell’OR fra i due bit corrispondenti degli operandi)
L’operatore AND può essere utilizzato per “leggere” il contenuto di un singolo bit all’interno di una parola.
Dalla tabella di verità dell’operatore AND si può vedere che X AND 0 = 0, qualunque sia il valore di X
(infatti, perché l’operatore AND restituisca il valore vero bisogna che entrambi gli operandi abbiano valore
vero). Analogamente, X AND 1 = X. Allora, per conoscere il valore del bit più significativo di una parola K,
ad es. di 8 bit, si può eseguire l’operazione K AND 10000000, cioè applicare l’AND a K e a una parola
composta da tutti zeri eccetto un 1 nella posizione che vogliamo leggere. In questo modo, il risultato per i bit
meno significativi sarà sicuramente 0, mentre il risultato sul bit più significativo sarà uguale al contenuto del
bit più significativo di K. Quindi basterà verificare se la parola ottenuta ottenuto è o meno uguale a zero (il
confronto con lo zero fa sempre parte del set di istruzioni di una CPU): se è 0 allora il bit che abbiamo
“letto” ha valore 0, se è diversa da 0 allora il bit è uguale a 1.
4
Es.
Determinare il valore del quinto bit (a partire dal meno significativo) della seguente parola:
K = 01011000
*
Eseguo K AND 00010000
Il risultato è 00010000, diverso da 0, quindi il bit che ho letto è uguale ad 1.
Se fosse stato 0 il risultato sarebbe stato 00000000.
Agli operatori booleani già visti si aggiungono anche i due operatori di shift (scorrimento) a destra e shift a
sinistra. Il risultato di tali operatori è una parola derivata dalla parola cui sono applicati facendo scorrere ogni
bit di una posizione a destra o a sinistra. Nel caso dello shift a destra (Shift Right, SHR), il bit più
significativo diventa 0 e il bit meno significativo “sparisce”; nel caso dello shift a sinistra (Shift Left, SHL),
il bit meno significativo diventa 0 e, se consideriamo una rappresentazione con un numero finito di bit, il bit
più significativo “sparisce”, altrimenti si sposta di una posizione a sinistra come tutti gli altri e la parola
risultante sarà più lunga di un bit rispetto a quella cui l’operatore è stato applicato.
Es.
P = 11001001
SHR(P) =
01100100
SHL(P) =
110010010
10010010
(ogni bit si è spostato a destra di una posizione; il MSB è diventato 0).
se si hanno a disposizione più di 8 bit per rappresentare il risultato
se anche il risultato è rappresentato su 8 bit
(ogni bit si è spostato a sinistra di una posizione; il LSB è diventato 0).
5