Un’espressione booleana è una formula simbolica che combina variabili logiche e operatori per descrivere una relazione di verità. Così come in aritmetica si scrive 3 × (x + 2) per rappresentare un calcolo numerico, in logica booleana si scrive A AND (B OR NOT C) per rappresentare una condizione logica. La potenza di questa notazione sta nella sua precisione: elimina ogni ambiguità del linguaggio naturale.
Nella programmazione questa precisione è indispensabile. Ogni volta che scriviamo una condizione in un if, in un while o in qualsiasi altra struttura di controllo, stiamo scrivendo un’espressione booleana. Capire come si costruisce, come si valuta e come si semplifica un’espressione booleana significa capire come il programma prende le sue decisioni.
Questa lezione accompagna lo studente attraverso cinque passaggi fondamentali: imparare a scrivere espressioni formali a partire da problemi reali, capire le regole di precedenza degli operatori, valutare un’espressione sostituendo valori concreti, comprendere il comportamento di PHP e JavaScript nelle espressioni booleane, e infine costruire e interpretare la tabella di verità corrispondente.
Notazione Simbolica delle Espressioni Booleane
Le variabili booleane assumono solo due valori possibili: 0 (falso) e 1 (vero). Gli operatori fondamentali sono tre:
- NOT, scritto anche come
¬AoppureA'oppureĀ, che nega il valore di una variabile; - AND, scritto anche come
A · Boppure semplicementeAB, che restituisce 1 solo se entrambe le variabili sono 1; - OR, scritto anche come
A + B, che restituisce 1 se almeno una delle variabili è 1.
In questa lezione si adotterà prevalentemente la notazione NOT A, A AND B, A OR B per favorire la leggibilità, affiancata dalla sintassi PHP e JavaScript !, &&, || negli esempi pratici.
Un’espressione booleana è qualsiasi combinazione valida di variabili, operatori e parentesi. Ecco alcuni esempi, dal più semplice al più articolato:
A AND B— semplice congiunzione di due variabili;NOT A OR B— negazione di A messa in OR con B;(A OR B) AND (NOT C)— uso delle parentesi per raggruppare;A AND B OR NOT C AND D— espressione più complessa che richiede la conoscenza delle precedenze.
L’ultimo esempio solleva una domanda immediata: qual è l’ordine in cui vanno applicati gli operatori? Prima di rispondere, impariamo a costruire queste espressioni a partire da problemi concreti.
Dalla Lingua Naturale all’Espressione Formale
Tradurre un problema dal linguaggio naturale a un’espressione booleana è una competenza centrale, sia nella logica formale che nella programmazione. La procedura richiede di identificare le variabili, riconoscere i connettivi logici e rispettare le sfumature semantiche.
Esempio 1. «Il sistema si attiva se l’interruttore A è chiuso e l’interruttore B è chiuso.»
Le variabili sono A e B, il connettivo è «e» (AND). L’espressione logica è A AND B, che in PHP si scrive:
<?php
$interruttore_a = true;
$interruttore_b = true;
$sistema_attivo = $interruttore_a && $interruttore_b;
var_dump($sistema_attivo); // Output: bool(true)
?>
Esempio 2. «L’allarme scatta se la porta è aperta oppure se la finestra è aperta, ma solo quando il sistema è armato.»
Le variabili sono P (porta aperta), F (finestra aperta), S (sistema armato). L’espressione è (P OR F) AND S. Le parentesi sono necessarie perché l’attivazione dipende dalla condizione composta «porta o finestra», e questa deve essere vera insieme all’armamento del sistema.
<?php
$porta_aperta = true;
$finestra_aperta = false;
$sistema_armato = true;
$allarme = ($porta_aperta || $finestra_aperta) && $sistema_armato;
var_dump($allarme); // Output: bool(true)
?>
Esempio 3. «L’accesso è negato se l’utente non è autenticato o se il suo livello di privilegio non è sufficiente.»
Le variabili sono A (utente autenticato) e L (livello sufficiente). La frase dice «non è autenticato», che si traduce in NOT A, e «non è sufficiente», che diventa NOT L. Il connettivo «o» corrisponde a OR. L’espressione per «accesso negato» è (NOT A) OR (NOT L).
let utenteAutenticato = false;
let livelloSufficiente = true;
let accessoNegato = !utenteAutenticato || !livelloSufficiente;
console.log(accessoNegato); // Output: true
Il percorso inverso: dall’espressione al linguaggio naturale. La traduzione funziona anche nella direzione opposta. Data l’espressione A AND (NOT B OR C), si legge: «A è vero, e inoltre è vero almeno uno tra: B è falso oppure C è vero.»
Precedenza degli Operatori
Sappiamo scrivere espressioni booleane, ma come si leggono quando mancano le parentesi? Così come in aritmetica la moltiplicazione precede l’addizione, in algebra booleana esiste una gerarchia precisa degli operatori. Questa gerarchia vale sia nella matematica formale sia nel codice PHP e JavaScript.
| Priorità | Operatore | PHP / JavaScript | Analogia aritmetica |
|---|---|---|---|
| 1 (massima) | NOT | ! | cambio di segno, negazione unaria |
| 2 | AND | && | moltiplicazione |
| 3 (minima) | OR | || | addizione |
Questa gerarchia significa che, in assenza di parentesi, si applica prima NOT a ogni singola variabile, poi si eseguono tutti gli AND, e infine si eseguono gli OR.
Esempio pratico. Consideriamo l’espressione:
A OR NOT B AND C
Senza conoscere le precedenze, verrebbe naturale leggere da sinistra a destra. Invece la valutazione corretta è:
- Passo 1: applicare NOT →
NOT Bviene calcolato per primo; - Passo 2: applicare AND →
(NOT B) AND C; - Passo 3: applicare OR →
A OR ((NOT B) AND C).
Il risultato è quindi molto diverso da (A OR NOT B) AND C, che avrebbe un significato logico completamente differente. In PHP:
<?php
$A = true;
$B = true;
$C = false;
// Senza parentesi: PHP applica le precedenze NOT > AND > OR
$risultato = $A || !$B && $C;
// Equivale a: $A || ((!$B) && $C)
// = true || (false && false)
// = true || false
// = true
var_dump($risultato); // Output: bool(true)
// Con parentesi esplicite che cambiano il significato:
$risultato2 = ($A || !$B) && $C;
// = (true || false) && false
// = true && false
// = false
var_dump($risultato2); // Output: bool(false)
?>
I due risultati sono diversi. Questo esempio mostra concretamente perché conoscere la precedenza degli operatori è essenziale per scrivere codice corretto.
Uso delle Parentesi
Le parentesi consentono di forzare un ordine di valutazione diverso da quello imposto dalle precedenze. Sono uno strumento essenziale per esprimere con precisione la logica desiderata e per rendere il codice più leggibile.
Confrontiamo due espressioni apparentemente simili:
| Espressione | Struttura effettiva | Significato |
|---|---|---|
A AND B OR C | (A AND B) OR C | Basta che C sia vero per rendere vera l’intera espressione |
A AND (B OR C) | A AND (B OR C) | A deve essere sempre vero, indipendentemente da B e C |
Un errore frequente nel codice. Consideriamo questa specifica: «L’irrigazione parte se il sensore di umidità rileva terreno secco e almeno uno tra il timer diurno o il timer notturno è attivo.» Le variabili sono U (umidità bassa), D (timer diurno), N (timer notturno).
Un errore frequente è scrivere:
<?php
// SBAGLIATO: per le precedenze equivale a (U && D) || N
$irrigazione = $U && $D || $N;
// L'irrigazione partirebbe ogni volta che il timer notturno è attivo,
// anche se il terreno è già bagnato.
?>
L’espressione corretta è:
<?php
// CORRETTO: le parentesi forzano la valutazione di (D || N) prima dell'AND con U
$irrigazione = $U && ($D || $N);
// L'irrigazione parte solo se il terreno è secco E almeno un timer è attivo.
?>
Regola pratica
Quando si ha dubbio sulla precedenza, è sempre meglio inserire parentesi esplicite. Le parentesi non alterano la correttezza di un’espressione già corretta, ma ne migliorano la leggibilità e prevengono errori di interpretazione. Nel codice professionale le parentesi sono considerate buona pratica anche quando non strettamente necessarie.
Valutazione di un’Espressione Booleana
Valutare un’espressione booleana significa sostituire valori concreti (0 o 1, oppure true o false) alle variabili e calcolare il risultato seguendo l’ordine di precedenza. È l’equivalente logico della sostituzione numerica in un’espressione algebrica.
Esempio completo. Valutiamo A AND (NOT B OR C) con i valori A = 1, B = 1, C = 0.
- Passo 1 — Sostituire i valori:
1 AND (NOT 1 OR 0) - Passo 2 — Applicare NOT (priorità massima):
NOT 1 = 0→1 AND (0 OR 0) - Passo 3 — Applicare OR (dentro le parentesi):
0 OR 0 = 0→1 AND 0 - Passo 4 — Applicare AND:
1 AND 0 = 0
Risultato: 0 (falso). In PHP:
<?php
$A = true; // 1
$B = true; // 1
$C = false; // 0
$risultato = $A && (!$B || $C);
// = true && (!true || false)
// = true && (false || false)
// = true && false
// = false
var_dump($risultato); // Output: bool(false)
?>
Secondo esempio. Stessa espressione con A = 1, B = 0, C = 0.
- Passo 1:
1 AND (NOT 0 OR 0) - Passo 2:
NOT 0 = 1→1 AND (1 OR 0) - Passo 3:
1 OR 0 = 1→1 AND 1 - Passo 4:
1 AND 1 = 1
Risultato: 1 (vero). In PHP:
<?php
$A = true; // 1
$B = false; // 0
$C = false; // 0
$risultato = $A && (!$B || $C);
// = true && (!false || false)
// = true && (true || false)
// = true && true
// = true
var_dump($risultato); // Output: bool(true)
?>
La Valutazione a Corto Circuito
PHP e JavaScript non valutano sempre tutte le parti di un’espressione booleana. Entrambi i linguaggi adottano la cosiddetta valutazione a corto circuito (in inglese short-circuit evaluation): non appena il risultato finale è determinabile, la valutazione si interrompe e le parti rimanenti non vengono calcolate.
Le regole sono due:
- in un’espressione
A AND B, se A è falso, il risultato è già determinato (sarà sempre falso) e B non viene mai valutato; - in un’espressione
A OR B, se A è vero, il risultato è già determinato (sarà sempre vero) e B non viene mai valutato.
Questo comportamento ha conseguenze importanti per chi scrive codice. Vediamo un esempio pratico in PHP:
<?php
function controlla_database() {
echo "Funzione eseguita!";
return true;
}
$connessione_attiva = false;
// Grazie al corto circuito, controlla_database() non viene mai chiamata
// perché $connessione_attiva è false e l'AND è già determinato (false)
$risultato = $connessione_attiva && controlla_database();
var_dump($risultato);
// Output: bool(false)
// La stringa "Funzione eseguita!" NON appare: la funzione non è stata chiamata
?>
function controllaSistema() {
console.log("Funzione eseguita!");
return true;
}
let utenteAdmin = true;
// Grazie al corto circuito, controllaSistema() non viene mai chiamata
// perché utenteAdmin è true e l'OR è già determinato (true)
let accesso = utenteAdmin || controllaSistema();
console.log(accesso);
// Output: true
// La stringa "Funzione eseguita!" NON appare: la funzione non è stata chiamata
Il corto circuito non è solo un dettaglio tecnico: è uno strumento che i programmatori usano deliberatamente per scrivere codice più efficiente e per prevenire errori. Un uso classico in PHP è la verifica che un oggetto esista prima di accedere a un suo metodo:
<?php
// Senza corto circuito, se $utente fosse null la seconda condizione
// causerebbe un errore fatale. Il corto circuito lo previene:
// se $utente è null (falso), PHP non valuta nemmeno $utente->isAdmin()
if ($utente !== null && $utente->isAdmin()) {
echo "Benvenuto, amministratore!";
}
?>
Valori Truthy e Falsy
PHP e JavaScript permettono di usare valori non booleani all’interno di espressioni booleane. Quando un valore non booleano viene usato in un contesto che richiede true o false, il linguaggio lo converte automaticamente. Questa conversione implicita è nota come type coercion (coercizione di tipo).
I valori che vengono convertiti a false sono chiamati falsy; quelli che vengono convertiti a true sono chiamati truthy.
Valori Falsy in PHP
In PHP i seguenti valori vengono considerati false in un contesto booleano:
| Valore | Tipo | Risultato booleano |
|---|---|---|
false | booleano | false |
0 | intero | false |
0.0 | float | false |
"" (stringa vuota) | stringa | false |
"0" | stringa | false |
[] (array vuoto) | array | false |
null | null | false |
Qualsiasi altro valore — un numero diverso da zero, una stringa non vuota, un array con elementi — è considerato true.
<?php
var_dump((bool) 0); // bool(false)
var_dump((bool) 1); // bool(true)
var_dump((bool) ""); // bool(false)
var_dump((bool) "ciao"); // bool(true)
var_dump((bool) []); // bool(false)
var_dump((bool) [1, 2]); // bool(true)
var_dump((bool) null); // bool(false)
?>
Valori Falsy in JavaScript
In JavaScript i valori falsy sono:
| Valore | Tipo | Risultato booleano |
|---|---|---|
false | booleano | false |
0 | numero | false |
-0 | numero | false |
"" (stringa vuota) | stringa | false |
null | null | false |
undefined | undefined | false |
NaN | numero | false |
console.log(Boolean(0)); // false
console.log(Boolean(1)); // true
console.log(Boolean("")); // false
console.log(Boolean("ciao")); // true
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean([])); // true ← attenzione: diverso da PHP!
console.log(Boolean({})); // true
Attenzione: array vuoto in JavaScript
In PHP un array vuoto
[]è falsy. In JavaScript invece un array vuoto[]è truthy, perché è un oggetto e qualsiasi oggetto è truthy in JavaScript. Questa differenza è una fonte comune di errori per chi lavora con entrambi i linguaggi. Quando si vuole verificare se un array è vuoto in JavaScript, bisogna controllare esplicitamente la sua proprietàlength:array.length === 0.
Conseguenze pratiche nel Codice
La conversione implicita permette di scrivere codice più conciso, ma può causare comportamenti inattesi se non la si conosce bene.
<?php
$nome_utente = ""; // stringa vuota = falsy
// Questo if NON viene eseguito perché "" è falsy
if ($nome_utente) {
echo "Benvenuto, " . $nome_utente;
} else {
echo "Nome utente mancante."; // Questa riga viene eseguita
}
$lista_prodotti = []; // array vuoto = falsy
// Questo if NON viene eseguito perché [] è falsy
if ($lista_prodotti) {
echo "Ci sono prodotti nel carrello.";
} else {
echo "Il carrello è vuoto."; // Questa riga viene eseguita
}
?>
let nomeUtente = "";
if (nomeUtente) {
console.log("Benvenuto, " + nomeUtente);
} else {
console.log("Nome utente mancante."); // Questa riga viene eseguita
}
let listaProdotti = []; // Attenzione: in JavaScript [] è truthy!
if (listaProdotti) {
console.log("Il carrello esiste."); // Questa riga VIENE eseguita
} else {
console.log("Il carrello non esiste.");
}
// Per verificare se l'array è davvero vuoto in JavaScript:
if (listaProdotti.length === 0) {
console.log("Il carrello è vuoto."); // Questa riga viene eseguita
}
Dall’Espressione alla Tabella di Verità
Data un’espressione booleana con n variabili, la sua tabella di verità ha 2ⁿ righe, una per ogni combinazione possibile dei valori delle variabili. Costruire la tabella è un processo sistematico che richiede di calcolare il risultato per ciascuna riga.
Esempio. Costruiamo la tabella di verità di F = A AND (NOT B OR C).
Le variabili sono tre (A, B, C), quindi le righe sono 2³ = 8. Le colonne intermedie (NOT B, NOT B OR C) rendono esplicito ogni passaggio del calcolo.
| A | B | C | NOT B | NOT B OR C | F = A AND (NOT B OR C) |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 1 | 1 | 0 |
| 0 | 0 | 1 | 1 | 1 | 0 |
| 0 | 1 | 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 | 1 | 0 |
| 1 | 0 | 0 | 1 | 1 | 1 |
| 1 | 0 | 1 | 1 | 1 | 1 |
| 1 | 1 | 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 0 | 1 | 1 |
Possiamo verificare la tabella con il codice, calcolando F per ciascuna combinazione:
<?php
// Verifica della tabella di verità per F = A AND (NOT B OR C)
$combinazioni = [
[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1],
[1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]
];
foreach ($combinazioni as $c) {
$A = (bool) $c[0];
$B = (bool) $c[1];
$C = (bool) $c[2];
$F = $A && (!$B || $C);
echo "A={$c[0]} B={$c[1]} C={$c[2]} → F=" . ($F ? 1 : 0) . "\n";
}
?>
L’output corrisponderà esattamente alla colonna F della tabella: 0 0 0 0 1 1 0 1.
Esercizi di Verifica
Esercizio 1 — Dalla Lingua Naturale all’Espressione
Traduci ciascuna delle seguenti frasi in un’espressione booleana formale. Definisci tu stesso le variabili e spiega il significato di ciascuna.
- «Il file viene salvato automaticamente se l’utente è connesso e ha modificato il documento negli ultimi cinque minuti.»
- «La promozione è applicabile se il cliente è registrato oppure se ha inserito un codice sconto valido.»
- «Il sistema manda una notifica se la temperatura supera la soglia e il sensore non è in modalità manutenzione.»
- «L’accesso al pannello di controllo è bloccato se l’utente non è amministratore o se la sessione è scaduta.»
Esercizio 2 — Precedenza degli Operatori
Per ciascuna delle seguenti espressioni, riscrivi aggiungendo parentesi esplicite che rendano chiaro l’ordine di valutazione, poi calcola il risultato per i valori indicati.
A OR NOT B AND C, con A = false, B = false, C = true.NOT A AND B OR C, con A = true, B = true, C = false.A AND B OR C AND D, con A = true, B = false, C = true, D = true.
Esercizio 3 — Valutazione passo per passo
Valuta ciascuna delle seguenti espressioni passo per passo, mostrando tutti i passaggi intermedi come negli esempi della lezione. Poi verifica il risultato scrivendo il codice PHP corrispondente.
NOT (A AND B) OR C, con A = true, B = true, C = false.(A OR B) AND (NOT A OR C), con A = true, B = false, C = false.NOT A AND NOT B AND C, con A = false, B = true, C = true.
Esercizio 4 — Corto Circuito
Per ciascuno dei seguenti frammenti di codice PHP, indica se la seconda condizione viene valutata oppure no, e spiega perché. Poi indica il valore finale della variabile risultante.
<?php
function effettoCollaterale() {
echo "Chiamata!";
return true;
}
$A = false;
$B = true;
$C = true;
$r1 = $A && effettoCollaterale();
$r2 = $B || effettoCollaterale();
$r3 = $C && effettoCollaterale();
$r4 = $A || effettoCollaterale();
?>
Per ciascuna variabile ($r1, $r2, $r3, $r4): indica se la stringa «Chiamata!» viene stampata, e spiega il valore finale.
Esercizio 5 — Truthy e Falsy
Per ciascuno dei seguenti valori PHP, indica se è truthy o falsy e spiega perché. Poi verifica usando var_dump((bool) $valore).
$a = 0;$b = "false";(una stringa contenente la parola “false”)$c = [];$d = " ";(una stringa contenente uno spazio)$e = 0.0;$f = "0";$g = -1;$h = null;
Dopo aver completato l’esercizio per PHP, ripetilo per JavaScript evidenziando le differenze.
Esercizio 6 — Tabella di Verità
Costruisci la tabella di verità completa per ciascuna delle seguenti espressioni, mostrando le colonne intermedie. Poi scrivi il codice PHP che verifica tutti i casi usando un ciclo foreach come nell’esempio della lezione.
F = NOT (A OR B)F = (A AND B) OR (NOT A AND C)
Esercizio 7 — Dal Codice alla Logica
Leggi il seguente codice PHP e per ciascuna variabile risultante: scrivi l’espressione booleana in forma simbolica, costruisci la tabella di verità e indica il valore prodotto per i valori di input specificati.
<?php
$utente_loggato = true;
$abbonamento_premium = false;
$contenuto_gratuito = true;
$account_bloccato = false;
$puo_vedere = ($utente_loggato && $abbonamento_premium) || $contenuto_gratuito;
$accesso_negato = !$utente_loggato || $account_bloccato;
$richiede_upgrade = $utente_loggato && !$abbonamento_premium && !$contenuto_gratuito;
?>
Per ciascuna delle tre variabili risultanti: scrivi l’espressione simbolica, calcola il valore atteso con i valori forniti e spiega in linguaggio naturale cosa rappresenta quella condizione nel contesto di un sito web.