Overflow aritmetico: esercizi svolti

Indice dei contenuti

    L’overflow avviene quando il risultato di un’operazione supera l’intervallo rappresentabile con i bit disponibili: il valore “gira” (wrap-around) producendo un risultato sbagliato. Riconoscerlo è cruciale per la correttezza dei programmi. Questa scheda allena il rilevamento dell’overflow in complemento a due e senza segno.

    1. Overflow in complemento a due

    Esercizio. Su 8 bit (compl. a 2, intervallo [-128,127]), calcolare 100+50 e verificare l’overflow.

    100=01100100_2, 50=00110010_2:

    01100100+00110010=10010110_2.

    Il risultato 10010110_2 ha MSB = 1 → interpretato come negativo: vale -106. Ma 100+50=150>127: overflow. Sommando due positivi è uscito un negativo: segnale inequivocabile di overflow.

    2. Regola del segno per l’overflow

    Esercizio. Enunciare la regola per rilevare l’overflow in complemento a due.

    L’overflow in complemento a due si verifica quando:

    \text{due operandi di segno uguale danno un risultato di segno opposto.}

    • positivo + positivo = negativo → overflow;
    • negativo + negativo = positivo → overflow;
    • segni diversi → mai overflow (il risultato sta sempre nell’intervallo).

    Tecnicamente: overflow se il riporto entrante e quello uscente dal bit di segno differiscono.

    3. Riporto contro overflow

    Esercizio. Distinguere riporto (carry) e overflow nella somma 11111111_2+00000001_2 su 8 bit.

    Il risultato è 1\,00000000: c’è un riporto oltre l’8° bit.

    • In interpretazione senza segno (255+1): overflow (256 non rappresentabile su 8 bit).
    • In interpretazione con segno (-1+1=0): nessun overflow, risultato corretto 0.

    Riporto e overflow sono concetti diversi: il carry riguarda i senza segno, l’overflow i numeri con segno. La stessa operazione può avere carry ma non overflow.

    4. Overflow nei numeri senza segno

    Esercizio. Su 8 bit senza segno (intervallo [0,255]), calcolare 200+100.

    200+100=300>255\ \Rightarrow\ \text{overflow senza segno}.

    Il risultato gira: 300-256=44. La CPU produce 44 (i 9 bit reali sono 100101100, scartando il 9°). Per i senza segno l’overflow è segnalato dal carry oltre l’ultimo bit.

    5. Wrap-around

    Esercizio. Su 8 bit senza segno, cosa restituisce 255+1 e perché?

    255+1=256\equiv0\ (\text{mod }256).

    Il risultato “gira” a 0: è il wrap-around. L’aritmetica su n bit è in realtà modulo 2^n. È il bug classico dei contatori che azzerano dopo il massimo (es. il “millennium bug” e gli overflow dei timer).

    6. Conseguenze pratiche e prevenzione

    Esercizio. Come si previene o rileva l’overflow in pratica?

    Strategie tipiche:

    • usare tipi più larghi: passare da 8 a 16 o 32 bit estende l’intervallo (es. da \pm127 a \pm32767);
    • controllare i flag di stato: le CPU espongono un flag di overflow (V) e di carry (C) dopo ogni operazione;
    • verificare prima dell’operazione: controllare che gli operandi non portino fuori intervallo.

    Ignorare l’overflow produce risultati silenziosamente errati: è una delle cause più insidiose di bug e vulnerabilità.

    7. Overflow negativo

    Esercizio. Su 8 bit in complemento a due, verificare se -100+(-50) produce overflow.

    L’intervallo è [-128,127]. Il risultato matematico è:

    -100-50=-150< -128,

    quindi il risultato non è rappresentabile. Vediamolo sui bit:

    -100=10011100_2,\qquad -50=11001110_2.

    Somma:

    \begin{array}{r} 10011100\\ +\ 11001110\\\hline 1\ 01101010 \end{array}

    Scartando il nono bit resta 01101010_2=106, positivo. Due negativi hanno prodotto un positivo: è overflow. Il pattern 01101010 non va letto come risultato valido della somma con segno.

    8. Overflow nella sottrazione

    Esercizio. Su 8 bit in complemento a due, valutare 100-(-50).

    La sottrazione diventa una somma:

    100-(-50)=100+50=150.

    Il valore 150 supera il massimo 127, quindi ci sarà overflow. In bit:

    100=01100100_2,\qquad 50=00110010_2,

    e la somma è:

    01100100+00110010=10010110_2.

    Il risultato ha segno negativo, pur provenendo da due addendi positivi. Regola operativa: nella sottrazione a-b, prima si considera a+(-b) e poi si applica la stessa regola dei segni dell’addizione.

    9. Controllo preventivo senza calcolare la somma

    Esercizio. Come controllare se a+b può andare in overflow prima di sommare, usando interi con segno su 8 bit?

    Per l’intervallo [-128,127]:

    • se b>0, serve a\le127-b;
    • se b<0, serve a\ge-128-b;
    • se b=0, l’operazione è sempre sicura.

    Esempio: per a=90, b=40:

    127-b=127-40=87.

    Poiché 90>87, la somma 90+40 andrà in overflow. Questo controllo è usato nelle librerie sicure quando il linguaggio o la piattaforma non garantiscono eccezioni automatiche sull’overflow.

    10. Aritmetica saturata contro wrap-around

    Esercizio. Su 8 bit senza segno, confrontare il risultato di 250+20 con wrap-around e con saturazione.

    Il risultato matematico è:

    250+20=270.

    Su 8 bit senza segno il massimo è 255.

    • Wrap-around: si lavora modulo 256, quindi 270-256=14.
    • Saturazione: si blocca il risultato al massimo rappresentabile, quindi 255.

    Le CPU general purpose usano normalmente aritmetica modulo; molte istruzioni SIMD per audio, immagini e segnali offrono anche aritmetica saturata, perché in quei domini è preferibile troncare al massimo piuttosto che far girare il valore a un numero piccolo.

    Errori comuni

    • Confondere carry e overflow. Il carry riguarda i senza segno, l’overflow i numeri con segno: sono flag distinti.
    • Pensare che segni diversi diano overflow. Sommando un positivo e un negativo l’overflow è impossibile in complemento a due.
    • Dimenticare che la sottrazione è una somma. Per a-b va analizzata l’addizione a+(-b), con le stesse regole dell’overflow con segno.
    • Ignorare il wrap-around. L’aritmetica a n bit è modulo 2^n: superato il massimo si riparte da zero, non si “blocca”.
    • Affidarsi a tipi troppo piccoli. Per somme di valori grandi servono tipi più larghi: l’overflow silenzioso è una fonte di bug gravi.

    Ultimo aggiornamento: