Variabili Booleane ed Espressioni Logiche

Una variabile booleana p è un simbolo che prende un valore booleano: p è uguale a vero, oppure è uguale a falso, non può mai assumere i due valori allo stesso tempo, e deve sempre essere uguale a uno (e uno solo) dei due. L'aggettivo booleano si deve a George Boole, il pioniere della logica matematica.

In python i due valori booleani sono dei dati primitivi, rappresentati dai simboli True e False. In pratica, True e False sono altre due parole chiave (keyword) che sono riservate all'interprete del linguaggio, e non possono essere usate per definire variabili o funzioni.


In [1]:
True


Out[1]:
True

In [2]:
True = 13


  File "<ipython-input-2-228d079dfe90>", line 1
    True = 13
             ^
SyntaxError: can't assign to keyword

In qualsiasi linguaggio di programmazione, oltre ad espressioni aritmetiche, è possibile valutare delle espressioni logiche, utilizzando gli operatori logici and, or, e not:


In [3]:
True and False


Out[3]:
False

In [4]:
True or False


Out[4]:
True

In [5]:
False and False or True


Out[5]:
True

In [6]:
True or False and False


Out[6]:
True

DOMANDA: guardando gli ultimi due esempi, si riesce a capire se l'operatore and ha la precedenza sull'operatore or? La descrizione completa delle precedenze sugli operatori si trova nella documentazione ufficiale

Anche per gli operatori logici è possibile usare una notazione prefix, importando la libreria operator:


In [7]:
# Importa dalla libreria solo i tre operatori logici
from operator import and_, or_, not_

In [8]:
not_(or_(True, and_(False, True)))


Out[8]:
False

In alternativa, per dichiarare una precedenza tra gli operatori si possono usare le parentesi tonde:


In [9]:
not (True or (False and True))


Out[9]:
False

Operatori di confronto

Oltre agli operatori logici è possibile utilizzare gli operatori di confronto seguenti:

Simbolo matematico Keyword Python Notazione prefix
$a < b$ a < b lt(a, b)
$a \leq b$ a <= b le(a, b)
$a > b$ a > b gt(a, b)
$a \geq b$ a >= b ge(a, b)
$a = b$ a == b eq(a, b)

IMPORTANTE: non si confonda l'operatore di assegnamento = con l'operatore di confronto ==, in quanto hanno due significati completamente diversi.


In [10]:
True == True


Out[10]:
True

In [11]:
6*3 < 7*2


Out[11]:
False

In [12]:
14*2 == 4*7


Out[12]:
True

In [13]:
from operator import lt, le, gt, ge, eq

In [14]:
eq(14*2, 4*7)


Out[14]:
True

Espressioni condizionali e predicati

Qualsiasi linguaggio di programmazione deve avere un modo per poter verificare delle condizioni particolari e applicare delle procedure specifiche in base all'esito di tali condizioni. Ovvero, si devono poter definire delle espressioni condizionali. In python la sintassi per le espressioni condizionali è la seguente:

if <predicato1>:
    <body1>
elif <predicato2>:
    <body2>
else:
    <body3>

Per predicato si intende una espressione logica o una procedura (meglio, una funzione) che restituisce un valore boolean, ovvero True o False.

Per definire delle espressioni logiche, si possono utilizzare gli operatori di confronto e gli operatori logici (o nuovi predicati definiti nel programma che si sta scrivendo).

ESEMPIO:


In [15]:
if not 3 > 4:
    a = 3*2
else:
    a = 4*2

In [16]:
a


Out[16]:
6

In [17]:
print(a)


6

In [18]:
def Test(x):
    return x > 5 and x < 10

In [19]:
Test(2)


Out[19]:
False

In [20]:
Test(6)


Out[20]:
True

In [21]:
def ThreeAnd(x,y,z):
    return x and y and z

In [22]:
ThreeAnd(2>4, 1<2, 1==3)


Out[22]:
False

In [23]:
def Abs(x):
    if x >= 0:
        return x
    else:
        return -x

In [24]:
Abs(-3)


Out[24]:
3

In [25]:
Abs(5)


Out[25]:
5

Esercizi

ESERCIZIO 1.1: Viene data sotto una serie di espressioni. Qual è il risultato dell'interprete in risposta a ciascuna espressione? Si assuma che la sequenza viene valutata nell'ordine in cui vi viene presentata.

from operator import add, sub, mul
10
5 + 3 + 4
sub(9, 1)
add(mul(2, 4), sub(4, 6))
a = 3
b = add(a, 1)
a = b
b = add(a, add(b, mul(a, b)))
if gt(a, b) = lt(b, mul(a, b)):
    print(b)
else:
    print(a)

In [ ]:

ESERCIZIO 1.2: Si traduca l'espressione seguente in notazione prefix:

$\frac{5+4+(2 - (3 - ( 6 + \frac{4}{5})))}{3(6-2)(2-7)}$


In [ ]:

ESERCIZIO 1.3: Si scriva una procedura che prenda tre numeri come argomenti e restituisca la somma dei quadrati dei due numeri più grandi.


In [ ]:

ESERCIZIO 1.4: Si osservi che il modello di valutazione dell'interprete visto sino ad ora permette la valutazione di procedure in cui si hanno procedure composte. Si osservi l'esempio seguente e si commenti il comportamento dell'interprete in questo caso:


In [ ]:
def F(a, b):
    if b > 0:
        return add
    else:
        return sub
    
def G(a, b):
    return F(a,b)(a,b)

In [ ]:
G(-2,-3)

ESERCIZIO 1.5: Il sig. Bit ha inventato un test per determinare se l'interprete del linguaggio che sta usando segue un applicative-order evaluation oppure un normal-order evaluation. L'idea è di definire due procedure:


In [ ]:
def P():
    return P()

In [ ]:
def Test(x, y):
    if x == 0:
        return 0
    else:
        return y

e poi de valutare l'espressione:

Test(0,P())

Quale comportamento osserverà il signor Bit con un interprete che usa una applicative-order evaluation? Quale comportamento osserverà con un interprete che usa una normal-order evaluation? Spiegare la risposta data.


In [ ]:
Test(0,P())

In [ ]: