Vai al contenuto

Fondamenti di informatica - Laurea triennale Informatica/Rappresentazione dei numeri frazionari

Wikibooks, manuali e libri di testo liberi.
Indice del libro

Il computer memorizza numeri con la parte frazionaria usando la virgola mobile (floating-point), un’idea simile alla notazione scientifica: si salva il segno, una mantissa (le cifre significative) e un esponente (che dice dove “mettere” il punto binario, cioè il radix point). Siccome i bit disponibili sono finiti, i numeri reali vengono spesso approssimati e possono comparire errori di arrotondamento/troncamento.

Come funziona l’esempio a 8 bit (semplificato)

[modifica | modifica sorgente]

Con 1 byte:

  • 1 bit di segno: 0 = positivo, 1 = negativo
  • 3 bit di esponente: memorizzato in “excess notatiion” (vedi modulo precedente)
  • 4 bit di mantissa: le cifre significative del numero in binario

Per decodificare un byte:

  1. prendi la mantissa e metti il punto binario a sinistra (tipo .1011)
  2. leggi l’esponente (con la codifica excess) e sposta il punto a destra o sinistra
  3. applica il segno

Normalizzazione (normalized form)

[modifica | modifica sorgente]

Quando si memorizza un numero, si copiano i bit nella mantissa partendo dal primo 1 più a sinistra della rappresentazione binaria. Questo evita rappresentazioni multiple dello stesso valore (cioè rende la forma “unica”).

  • Per tutti i numeri non zero, la mantissa in forma normalizzata inizia con 1.
  • Zero è un caso speciale: tutti i bit a 0.

Formati reali: single e double precision

[modifica | modifica sorgente]

Il byte a 8 bit è solo didattico. Nella pratica:

  • Single precision (32 bit): 1 segno, 8 esponente, 23 mantissa → circa 7 cifre decimali di precisione
  • Double precision (64 bit) → circa 15 cifre decimali di precisione Più bit nella mantissa = meno errore, ma l’errore non sparisce sempre.

Errori di troncamento (truncation / round-off)

[modifica | modifica sorgente]

Se la mantissa non è abbastanza lunga, alcuni bit “in fondo” vengono tagliati e il numero memorizzato diventa leggermente diverso. Esempio: un valore come 2⅝ in binario richiede più bit di quelli disponibili e quindi viene salvato come un valore più vicino ma non uguale.

Un’altra fonte di errore è che alcuni numeri hanno espansioni non terminanti in binario (come 1/10), quindi non possono essere rappresentati esattamente con un numero finito di bit. Per questo, ad esempio, per denaro spesso conviene usare interi (centesimi) invece di float.

Perché l’ordine delle somme conta

[modifica | modifica sorgente]

Quando sommi numeri in virgola mobile, se aggiungi un numero molto piccolo a uno molto grande, il piccolo può “sparire” per troncamento. Per ridurre l’errore, conviene spesso sommarli dal più piccolo al più grande, così i piccoli si accumulano prima di essere confrontati col grande.

I software moderni di solito mascherano questi problemi, ma in applicazioni sensibili (es. navigazione, calcoli scientifici) anche piccoli errori possono propagarsi e diventare importanti.

Ecco alcuni esempi di conversione decimale ↔ floating point notation usando il formato di esempio a 8 bit:

  • 1 bit segno
  • 3 bit esponente in excess-4 (bias=4) ⇒ valore_esponente = exp_bits − 4 (000→−4, 001→−3, 010→−2, 011→−1, 100→0, 101→+1, 110→+2, 111→+3)
  • 4 bit mantissa in forma normalizzata: copi i bit a partire dal primo 1 e metti il punto binario a sinistra della mantissa (tipo .1001), poi sposti il punto di valore_esponente.

Floating → Decimale

[modifica | modifica sorgente]

Esempio A: 0 110 1011

[modifica | modifica sorgente]
  • segno = 0 ⇒ positivo
  • exp = 110 = 6 ⇒ 6−4 = +2
  • mantissa = 1011.1011₂ Sposta il punto di +2: .1011₂10.11₂ 10.11₂ = 2 + 1/2 + 1/4 = 2.75 Risultato: 2.75

Esempio B: 0 011 1100

[modifica | modifica sorgente]
  • segno 0 ⇒ positivo
  • exp 011=3 ⇒ 3−4 = −1
  • mantissa 1100.1100₂ Sposta di −1: .1100₂.01100₂ .01100₂ = 1/4 + 1/8 = 0.375 Risultato: 0.375

Esempio C (negativo): 1 101 1000

[modifica | modifica sorgente]
  • segno 1 ⇒ negativo
  • exp 101=5 ⇒ 5−4 = +1
  • mantissa 1000.1000₂ Sposta di +1: .1000₂1.000₂ = 1 Applica segno: −1 Risultato: −1.0

Decimale → Floating

[modifica | modifica sorgente]

Regola pratica

[modifica | modifica sorgente]
  1. Converti in binario.
  2. Scrivi i bit a partire dal primo 1 nella mantissa (4 bit).
  3. Considera la mantissa come .mmmm e scegli l’esponente come numero di spostamenti del punto per tornare al numero originale.
  4. Codifica l’esponente in excess-4.
  5. Metti il segno.

Esempio D: 1.125 (cioè 1 + 1/8)

[modifica | modifica sorgente]

1.125₁₀ = 1.001₂

Mantissa: prendo dal primo 1 → 1001.1001₂

Per ottenere 1.001₂ da .1001₂ devo spostare il punto di +1: .10011.001

Esponente = +1 ⇒ in excess-4: +1 + 4 = 5 ⇒ 101

Segno 0

Byte: 0 101 1001


Esempio E: 0.375

[modifica | modifica sorgente]

0.375₁₀ = 0.011₂

Primo 1: 11… ⇒ mantissa 1100.1100₂

Da .1100₂ per ottenere 0.011₂ devo spostare −1: .1100.01100

Esponente = −1 ⇒ −1+4=3 ⇒ 011

Segno 0

Byte: 0 011 1100


Esempio F (troncamento): 2.625 (2 + 5/8)

[modifica | modifica sorgente]

2.625₁₀ = 10.101₂

Prendo dal primo 1: 10101… ma ho solo 4 bit ⇒ mantissa 1010 (perdo l’ultimo 1) ⇒ .1010₂

Per tornare vicino a 10.101₂ devo spostare di +2: .101010.10₂ (=2.5)

Esponente +2 ⇒ +2+4=6 ⇒ 110

Segno 0

Byte memorizzato: 0 110 1010 che vale 2.5, non 2.625 → errore di troncamento.