Lezione 02 · Sistemi di numerazione¶
Cosa impari
- la differenza tra sistemi di numerazione posizionali e non posizionali;
- le basi usate in informatica: decimale, binaria, ottale, esadecimale;
- a convertire un numero da qualsiasi base in base 10;
- a convertire un numero decimale in binario: divisioni successive per la parte intera, moltiplicazioni successive per la parte frazionaria;
- a passare da binario a ottale ed esadecimale (e viceversa) raggruppando i bit;
- a fare somma, sottrazione, moltiplicazione e divisione in binario.
Un computer lavora solo con 0 e 1, noi siamo abituati alle cifre da 0 a 9. In questa lezione impari a passare da un sistema all'altro e a fare i conti direttamente in binario. Sono gli esercizi più frequenti dello scritto di teoria.
Sistemi posizionali e non posizionali¶
Un sistema di numerazione è un insieme di simboli (le cifre) e di regole che associano a ogni sequenza di cifre uno e un solo valore numerico.
- Non posizionale: ogni simbolo vale sempre la stessa quantità, ovunque si trovi. Nel sistema romano
Lvale sempre 50. - Posizionale: il valore di una cifra dipende dalla sua posizione. In 1345 la cifra 5 vale 5 unità, il 4 vale 4 decine, il 3 tre centinaia, l'1 un migliaio.
| Posizione | 3 | 2 | 1 | 0 |
|---|---|---|---|---|
| Cifra | 1 | 3 | 4 | 5 |
| Peso | 10³ = 1000 | 10² = 100 | 10¹ = 10 | 10⁰ = 1 |
1345 = 1 × 1000 + 3 × 100 + 4 × 10 + 5 × 1
La regola generale¶
In un sistema posizionale con base (o radice) b, una cifra in posizione j ha peso bʲ. Le posizioni si contano da destra, partendo da 0, e la posizione 0 è quella subito a sinistra della virgola. Le cifre dopo la virgola hanno posizioni negative: −1, −2, …
Un numero con i cifre intere e k cifre frazionarie
c₍ᵢ₋₁₎ … c₁ c₀ , c₋₁ c₋₂ … c₋ₖ
vale:
x = c₍ᵢ₋₁₎ · bⁱ⁻¹ + … + c₁ · b¹ + c₀ · b⁰ + c₋₁ · b⁻¹ + c₋₂ · b⁻² + … + c₋ₖ · b⁻ᵏ
Due numeri reali in base 10 con 2 + 2 cifre
- 00,13 = 0 · 10¹ + 0 · 10⁰ + 1 · 10⁻¹ + 3 · 10⁻² = 0,1 + 0,03
- 10,40 = 1 · 10¹ + 0 · 10⁰ + 4 · 10⁻¹ + 0 · 10⁻² = 10 + 0,4
Le basi usate in informatica¶
In base b servono b simboli, per i valori da 0 a b − 1.
| Base | Nome | Cifre |
|---|---|---|
| 10 | decimale | 0 1 2 3 4 5 6 7 8 9 |
| 2 | binaria | 0 1 |
| 8 | ottale | 0 1 2 3 4 5 6 7 |
| 16 | esadecimale | 0 1 2 3 4 5 6 7 8 9 A B C D E F |
In esadecimale le lettere valgono: A = 10, B = 11, C = 12, D = 13, E = 14, F = 15.
Come si scrive la base. Si racchiude il numero tra parentesi e si scrive la base in basso a destra:
(101111)₂ = (142)₅ = (47)₁₀
Segno meno, operatori e virgola si scrivono come in decimale. Gli zeri a sinistra si possono togliere, e anche quelli a destra della parte frazionaria: (00101,100)₂ = (101,1)₂.
Come si legge. Solo in decimale si legge "quarantasette". Negli altri sistemi si leggono le cifre una per una, dalla più pesante, dicendo la base: (142)₅ si legge "uno quattro due in base cinque".
Da qualsiasi base a base 10¶
Basta applicare la regola generale: moltiplica ogni cifra per il suo peso e somma.
| Numero | Calcolo | Risultato |
|---|---|---|
| (101111)₂ | 1·2⁵ + 0·2⁴ + 1·2³ + 1·2² + 1·2¹ + 1·2⁰ = 32 + 8 + 4 + 2 + 1 | (47)₁₀ |
| (142)₅ | 1·5² + 4·5¹ + 2·5⁰ = 25 + 20 + 2 | (47)₁₀ |
| (47)₁₀ | 4·10¹ + 7·10⁰ | (47)₁₀ |
Il sistema binario¶
Il binario ha solo 2 simboli, quindi servono più cifre per scrivere lo stesso numero. Per avere almeno 10 configurazioni (come le cifre decimali) servono ⌈log₂ 10⌉ = 4 bit. In media un numero binario è circa 3,3 volte più lungo del corrispondente decimale.
Esempio svolto: (10101010)₂ in decimale
Scrivi i pesi sopra le cifre e somma solo quelli sotto cui c'è un 1.
| Peso | 2⁷ = 128 | 2⁶ = 64 | 2⁵ = 32 | 2⁴ = 16 | 2³ = 8 | 2² = 4 | 2¹ = 2 | 2⁰ = 1 |
|---|---|---|---|---|---|---|---|---|
| Cifra | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
| Contributo | 128 | 0 | 32 | 0 | 8 | 0 | 2 | 0 |
128 + 32 + 8 + 2 = (170)₁₀
Altri esempi: (1001101)₂ = 64 + 8 + 4 + 1 = (77)₁₀; (111100)₂ = (60)₁₀; (10100001)₂ = (161)₁₀; (1100010100)₂ = (788)₁₀.
Verifica con Python (facoltativo). La funzione int(testo, base) converte una stringa di cifre in un numero decimale.
print(int('10101010', 2)) # da binario
print(int('142', 5)) # da base 5
print(int('17E', 16)) # da esadecimale
print(int('576', 8)) # da ottale
numero = input('Scrivi un numero binario: ')
print('In decimale vale', int(numero, 2))
Ottale ed esadecimale¶
Le stringhe di bit diventano presto lunghe e difficili da leggere. Ottale ed esadecimale servono a scriverle in forma compatta. Il passaggio da e verso il binario è immediato perché 8 = 2³ e 16 = 2⁴: una cifra ottale corrisponde a 3 bit, una cifra esadecimale a 4 bit.
| Ottale | Binario | Esadecimale | Binario | Esadecimale | Binario | |
|---|---|---|---|---|---|---|
| 0 | 000 | 0 | 0000 | 8 | 1000 | |
| 1 | 001 | 1 | 0001 | 9 | 1001 | |
| 2 | 010 | 2 | 0010 | A | 1010 | |
| 3 | 011 | 3 | 0011 | B | 1011 | |
| 4 | 100 | 4 | 0100 | C | 1100 | |
| 5 | 101 | 5 | 0101 | D | 1101 | |
| 6 | 110 | 6 | 0110 | E | 1110 | |
| 7 | 111 | 7 | 0111 | F | 1111 |
- Binario → ottale: raggruppa i bit a gruppi di tre, partendo da destra (dal bit di peso minore). Se l'ultimo gruppo a sinistra è incompleto, aggiungi zeri a sinistra. Sostituisci ogni gruppo con la sua cifra.
- Ottale → binario: sostituisci ogni cifra ottale con i suoi 3 bit.
- Binario → esadecimale ed esadecimale → binario: stessa cosa, con gruppi di quattro.
Esempio svolto: (101111110)₂ in ottale e in esadecimale
Ottale, gruppi di 3 da destra:
| Gruppi | 101 | 111 | 110 |
|---|---|---|---|
| Cifra ottale | 5 | 7 | 6 |
(101111110)₂ = (576)₈
Esadecimale, gruppi di 4 da destra (il primo gruppo 1 diventa 0001):
| Gruppi | 0001 | 0111 | 1110 |
|---|---|---|---|
| Cifra esadecimale | 1 | 7 | E |
(101111110)₂ = (17E)₁₆
Da decimale a binario¶
Il metodo ha due passi.
- Separa la parte intera dalla parte frazionaria. Ad esempio 382,25 = 382 + 0,25.
- Converti le due parti con due algoritmi diversi e poi rimettile insieme.
Parte intera: divisioni successive per 2¶
Dividi il numero per 2 e annota quoziente e resto. Poi dividi il quoziente per 2, e così via, finché il quoziente diventa 0. I resti, letti dall'ultimo al primo, sono le cifre binarie.
- Il resto della prima divisione è il bit meno significativo (LSB, a destra).
- Il resto dell'ultima divisione è il bit più significativo (MSB, a sinistra).
Perché funziona
La parte intera si scrive d = cᵢ·2ⁱ + … + c₂·2² + c₁·2¹ + c₀. Tutti i termini tranne c₀ sono multipli di 2. Quindi dividendo d per 2 il resto è c₀ e il quoziente è cᵢ·2ⁱ⁻¹ + … + c₂·2¹ + c₁. Dividendo di nuovo per 2 il resto è c₁, e così via: ogni divisione "stacca" la cifra successiva.
Esempio svolto: (382)₁₀ in binario
| Divisione | Quoziente | Resto |
|---|---|---|
| 382 : 2 | 191 | 0 ← LSB |
| 191 : 2 | 95 | 1 |
| 95 : 2 | 47 | 1 |
| 47 : 2 | 23 | 1 |
| 23 : 2 | 11 | 1 |
| 11 : 2 | 5 | 1 |
| 5 : 2 | 2 | 1 |
| 2 : 2 | 1 | 0 |
| 1 : 2 | 0 | 1 ← MSB |
Leggendo i resti dal basso verso l'alto: (382)₁₀ = (101111110)₂.
Controllo: 256 + 64 + 32 + 16 + 8 + 4 + 2 = 382.
Parte frazionaria: moltiplicazioni successive per 2¶
Moltiplica la parte frazionaria per 2. La parte intera del prodotto (0 oppure 1) è la cifra binaria successiva. Poi scarta quella parte intera e moltiplica di nuovo per 2 solo la parte frazionaria. Le cifre si leggono nell'ordine in cui le ottieni, dall'alto verso il basso.
Ti fermi quando:
- la parte frazionaria diventa 0: la conversione è esatta;
- la parte frazionaria si ripete: il numero binario è periodico;
- hai ottenuto il numero di cifre richiesto: la rappresentazione è approssimata.
Perché funziona
La parte frazionaria si scrive f = c₋₁·2⁻¹ + c₋₂·2⁻² + c₋₃·2⁻³ + … Moltiplicando per 2 ottieni c₋₁ + c₋₂·2⁻¹ + c₋₃·2⁻² + … Il primo termine c₋₁ è un intero (0 o 1) e finisce a sinistra della virgola; tutto il resto è minore di 1. Quindi la parte intera del prodotto è proprio c₋₁, e la nuova parte frazionaria contiene le cifre successive.
Esempio svolto: (382,25)₁₀ in binario
La parte intera l'hai già convertita: (382)₁₀ = (101111110)₂. Ora la parte frazionaria 0,25:
| Frazione | × 2 | Parte intera |
|---|---|---|
| 0,25 | 0,50 | 0 |
| 0,50 | 1,00 | 1 |
La parte frazionaria è 0: conversione esatta. (0,25)₁₀ = (0,01)₂.
Quindi (382,25)₁₀ = (101111110,01)₂.
Esempio svolto: (82,84)₁₀ in binario, con 8 cifre dopo la virgola
Parte intera 82:
| Divisione | Quoziente | Resto |
|---|---|---|
| 82 : 2 | 41 | 0 |
| 41 : 2 | 20 | 1 |
| 20 : 2 | 10 | 0 |
| 10 : 2 | 5 | 0 |
| 5 : 2 | 2 | 1 |
| 2 : 2 | 1 | 0 |
| 1 : 2 | 0 | 1 |
Resti dal basso: (82)₁₀ = (1010010)₂.
Parte frazionaria 0,84:
| Frazione | × 2 | Parte intera |
|---|---|---|
| 0,84 | 1,68 | 1 |
| 0,68 | 1,36 | 1 |
| 0,36 | 0,72 | 0 |
| 0,72 | 1,44 | 1 |
| 0,44 | 0,88 | 0 |
| 0,88 | 1,76 | 1 |
| 0,76 | 1,52 | 1 |
| 0,52 | 1,04 | 1 |
| 0,04 | … | … |
Dopo 8 cifre la parte frazionaria (0,04) non è ancora zero: ci fermiamo e il risultato è approssimato.
(82,84)₁₀ ≈ (1010010,11010111)₂
Un numero decimale semplice può non esserlo in binario
0,1 in decimale ha una sola cifra, ma in binario è periodico: (0,1)₁₀ = (0,0001100110011…)₂. Il calcolatore deve tagliarlo, quindi lo memorizza in modo approssimato. Per questo in Python 0.1 + 0.2 dà 0.30000000000000004.
Da decimale a ottale o esadecimale¶
Il modo più semplice: converti prima in binario, poi raggruppa i bit.
| Numero | Binario | Gruppi da 4 | Esadecimale |
|---|---|---|---|
| (84)₁₀ | (1010100)₂ | 0101 0100 | (54)₁₆ |
| (382)₁₀ | (101111110)₂ | 0001 0111 1110 | (17E)₁₆ |
In alternativa puoi usare le divisioni successive per 16 (o per 8): i resti sono le cifre. Ad esempio 382 : 16 = 23 resto 14 (E); 23 : 16 = 1 resto 7; 1 : 16 = 0 resto 1. Dal basso: (17E)₁₆.
Verifica con Python (facoltativo). Il programma rifà le divisioni successive e stampa la tabella. Poi controlla il risultato con bin(), oct() e hex() (il prefisso 0b, 0o o 0x indica la base).
n = int(input('Numero intero da convertire: '))
originale = n
cifre = ''
print('Quoziente Resto')
while n > 0:
resto = n % 2
n = n // 2
print(f'{n:9} {resto:5}')
cifre = str(resto) + cifre # il nuovo resto va a SINISTRA
print('In binario:', cifre)
print('Controllo:', bin(originale), oct(originale), hex(originale))
E questo rifà le moltiplicazioni successive per la parte frazionaria, fermandosi dopo un numero massimo di cifre:
f = float(input('Parte frazionaria (es. 0.25): '))
max_cifre = int(input('Quante cifre al massimo? '))
cifre = ''
conta = 0
while f != 0 and conta < max_cifre:
f = f * 2
if f >= 1:
cifre = cifre + '1'
f = f - 1
else:
cifre = cifre + '0'
conta = conta + 1
print('In binario: 0,' + cifre)
if f != 0:
print('Risultato approssimato: la parte frazionaria non si è annullata')
Prova con 0.25 (esatto), con 0.84 e 8 cifre, e con 0.1 e 12 cifre (periodico).
Tool · Cambio di base
Risolvi prima l'esercizio a mano, poi controllalo qui: il tool mostra le stesse tabelle di divisioni e moltiplicazioni successive, lo sviluppo posizionale e il metodo veloce con i gruppi di bit. Funziona con qualsiasi base da 2 a 36.
Operazioni aritmetiche in binario¶
Somma, sottrazione, moltiplicazione e divisione funzionano come in decimale. Cambiano solo le tabelline, che sono molto più corte:
| a | b | a + b | a − b | a × b |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 1 con prestito di 1 | 0 |
| 1 | 0 | 1 | 1 | 0 |
| 1 | 1 | 0 con riporto di 1 | 0 | 1 |
Ricorda: in binario 1 + 1 = (10)₂, cioè "scrivo 0 e riporto 1". E 1 + 1 + 1 = (11)₂, cioè "scrivo 1 e riporto 1".
Addizione¶
Si parte da destra e il riporto si propaga a sinistra, come in decimale.
Esempio svolto: (1001010)₂ + (11011)₂
| 2⁶ | 2⁵ | 2⁴ | 2³ | 2² | 2¹ | 2⁰ | |
|---|---|---|---|---|---|---|---|
| Riporti | 1 | 1 | 1 | ||||
| 1 | 0 | 0 | 1 | 0 | 1 | 0 | |
| + | 1 | 1 | 0 | 1 | 1 | ||
| = | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
Colonna per colonna da destra: 0+1 = 1; 1+1 = 0 riporto 1; 0+0+1 = 1; 1+1 = 0 riporto 1; 0+1+1 = 0 riporto 1; 0+0+1 = 1; 1+0 = 1.
Risultato (1100101)₂. Controllo in decimale: 74 + 27 = 101 = (1100101)₂.
Sottrazione¶
Quando devi fare 0 − 1 chiedi un prestito alla prima cifra 1 a sinistra, come in decimale. Il prestito vale 2 nella colonna che lo riceve, quindi 0 − 1 diventa (10)₂ − 1 = 1. La cifra che ha prestato diventa 0, e gli eventuali 0 intermedi diventano 1.
Esempio svolto: (101)₂ − (010)₂
| 2² | 2¹ | 2⁰ | |
|---|---|---|---|
| 1 | 0 | 1 | |
| − | 0 | 1 | 0 |
| = | 0 | 1 | 1 |
- Colonna 2⁰: 1 − 0 = 1.
- Colonna 2¹: 0 − 1 non si può. Prendi in prestito dalla colonna 2²: l'1 diventa 0 e la colonna 2¹ diventa (10)₂ = 2. Ora 2 − 1 = 1.
- Colonna 2²: 0 − 0 = 0.
Risultato (011)₂ = (11)₂. Controllo: 5 − 2 = 3.
Esempio più lungo: (10100001)₂ − (1010101)₂ = (1001100)₂, cioè 161 − 85 = 76.
Moltiplicazione¶
È la più facile: ogni cifra del moltiplicatore è 0 o 1, quindi ogni prodotto parziale è tutto zeri oppure una copia del moltiplicando, spostata a sinistra. Alla fine sommi i prodotti parziali.
Esempio svolto: (10100001)₂ × (101)₂
| 2⁹ | 2⁸ | 2⁷ | 2⁶ | 2⁵ | 2⁴ | 2³ | 2² | 2¹ | 2⁰ | |
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | |||
| × | 1 | 0 | 1 | |||||||
| 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | |||
| + | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | ||
| + | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | ||
| = | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
Risultato (1100100101)₂. Controllo: 161 × 5 = 805.
Divisione¶
Si procede come la divisione in colonna decimale, ma ogni cifra del quoziente può essere solo 0 o 1: ti chiedi soltanto se il divisore "ci sta" nella parte di dividendo che stai considerando. Ad esempio (111)₂ : (101)₂, cioè 7 : 5: il divisore ci sta una volta, quoziente 1 e resto (10)₂ = 2.
Esempio svolto: (10001)₂ : (11)₂, cioè 17 : 3
Prendi le cifre del dividendo una alla volta, da sinistra.
| Passo | Parte considerata | 11 ci sta? | Cifra del quoziente | Resto parziale |
|---|---|---|---|---|
| 1 | 1 | no | 0 | 1 |
| 2 | 10 | no | 0 | 10 |
| 3 | 100 | sì: 100 − 11 = 1 | 1 | 1 |
| 4 | 10 (abbasso lo 0) | no | 0 | 10 |
| 5 | 101 (abbasso l'1) | sì: 101 − 11 = 10 | 1 | 10 |
Quoziente (00101)₂ = (101)₂ = 5, resto (10)₂ = 2. Controllo: 3 × 5 + 2 = 17.
Verifica con Python (facoltativo): converti in decimale, fai l'operazione e riconverti.
a = int('1001010', 2)
b = int('11011', 2)
print('somma:', bin(a + b), '=', a + b)
print('differenza:', bin(int('10100001', 2) - int('1010101', 2)))
print('prodotto:', bin(int('10100001', 2) * int('101', 2)))
print('quoziente e resto:', bin(17 // 3), bin(17 % 3))
Tool · Somme e sottrazioni in colonna
Scrivi i due numeri in bit e scegli l'operazione: il tool mostra la riga dei riporti (o dei prestiti) come nelle tabelle qui sopra.
Errori frequenti negli esercizi¶
| Errore | Perché è sbagliato | Come si corregge |
|---|---|---|
| Leggere i resti dall'alto verso il basso | il primo resto è il bit meno significativo | scrivi i resti dall'ultimo al primo |
| Fermarsi quando il quoziente è 1 | manca l'ultima cifra (l'MSB) | continua finché il quoziente è 0 |
| Leggere al contrario le cifre della parte frazionaria | la prima moltiplicazione dà la cifra subito dopo la virgola | per la parte frazionaria leggi dall'alto verso il basso |
| Moltiplicare per 2 anche la parte intera del prodotto | la parte intera è già una cifra del risultato | togli la parte intera, moltiplica solo la frazione |
| Raggruppare i bit partendo da sinistra | i gruppi vengono sbagliati | per la parte intera raggruppa da destra, aggiungendo zeri a sinistra |
| Scrivere 1 + 1 = 2 in binario | in binario la cifra 2 non esiste | 1 + 1 = 0 con riporto 1 |
| Dimenticare l'ultimo riporto | il risultato ha una cifra in meno | se resta un riporto, scrivilo come nuova cifra a sinistra |
Esercizi¶
Esercizio 1 · Dal binario alle altre basi. Converti (110101)₂ in decimale, in ottale e in esadecimale.
Soluzione
Decimale:
| Peso | 32 | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|---|
| Cifra | 1 | 1 | 0 | 1 | 0 | 1 |
32 + 16 + 4 + 1 = (53)₁₀
Ottale, gruppi di 3 da destra: 110 | 101 → 6 | 5 → (65)₈
Esadecimale, gruppi di 4 da destra: 0011 | 0101 → 3 | 5 → (35)₁₆
Controllo: 6 × 8 + 5 = 53 e 3 × 16 + 5 = 53.
Esercizio 2 · Un numero con la virgola. Converti (45,375)₁₀ in binario, poi scrivi la parte intera in esadecimale.
Soluzione
Parte intera 45:
| Divisione | Quoziente | Resto |
|---|---|---|
| 45 : 2 | 22 | 1 |
| 22 : 2 | 11 | 0 |
| 11 : 2 | 5 | 1 |
| 5 : 2 | 2 | 1 |
| 2 : 2 | 1 | 0 |
| 1 : 2 | 0 | 1 |
Resti dal basso: (45)₁₀ = (101101)₂.
Parte frazionaria 0,375:
| Frazione | × 2 | Parte intera |
|---|---|---|
| 0,375 | 0,75 | 0 |
| 0,75 | 1,5 | 1 |
| 0,5 | 1,0 | 1 |
La frazione si annulla: (0,375)₁₀ = (0,011)₂, esatto.
Risultato: (45,375)₁₀ = (101101,011)₂.
Esadecimale della parte intera: 0010 | 1101 → 2 | D → (2D)₁₆. Controllo: 2 × 16 + 13 = 45.
Esercizio 3 · Conto in binario (come allo scritto). Calcola 85 + 98 così: converti i due numeri in binario, fai la somma in binario, riconverti il risultato in decimale e verifica.
Soluzione
Conversioni con le divisioni successive: (85)₁₀ = (1010101)₂ e (98)₁₀ = (1100010)₂.
Somma:
| 2⁷ | 2⁶ | 2⁵ | 2⁴ | 2³ | 2² | 2¹ | 2⁰ | |
|---|---|---|---|---|---|---|---|---|
| Riporti | 1 | |||||||
| 1 | 0 | 1 | 0 | 1 | 0 | 1 | ||
| + | 1 | 1 | 0 | 0 | 0 | 1 | 0 | |
| = | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 1 |
Solo nella colonna 2⁶ c'è 1 + 1 = 0 con riporto 1, che diventa la nuova cifra 2⁷.
Riconversione: (10110111)₂ = 128 + 32 + 16 + 4 + 2 + 1 = 183.
Verifica: 85 + 98 = 183. ✓