1.3.1 I sistemi di numerazione

Un sistema di numerazione è un modo per rappresentare dei valori numerici. Un numero si compone di cifre, cioè di simboli ad ognuno dei quali viene associato univocamente un valore diverso dagli altri.

I sistemi di numerazione moderni sono sistemi di numerazione posizionali, ovvero una stessa cifra ha un “peso” diverso dipendentemente dalla posizione che essa occupa all’interno del numero in questione. Per esempio nel numero 44, la cifra 4 che si trova a sinistra vale 10 volte di più di quella che le sta immediatamente a destra.

Da ciò nasce il concetto di base: la base indica il numero di cifre a disposizione del sistema di numerazione e, di conseguenza, quante volte di più vale la stessa cifra man mano che questa occupa una posizione sempre più a sinistra all’interno di un numero. Il sistema di numerazione decimale, o a base 10, con il quale si ha a che fare quotidianamente, ha dieci cifre diverse (da “0” a “9”) ed ogni cifra assume un significato 10 volte maggiore per ogni posizione che essa occupa spostandosi verso sinistra all’interno di un numero. Pertanto si può pensare che ad ogni posizione all’interno di un numero sia associato un “peso” che non è altro che una potenza della base del sistema di numerazione considerato.

1.3.1.1 Richiami di matematica

Nel corso della presente sezione si farà riferimento all’operazione di elevamento a potenza. Tale operazione identifica due entità, l’una detta base della potenza e l’altra detta esponente. La base è il valore che viene elevato alla potenza indicata dall’esponente. Indicando con b la base e con n l’esponente, la sintassi utilizzata per rappresentare l’operazione di elevamento alla potenza n-esima della base b è la seguente

 n
b

e si legge “b elevato alla n-esima potenza” o semplicemente “b alla n”. A tale scrittura viene associato il seguente significato

 n   prod n
b =    b = b-×-b× ...×-b
    i=1         n

ovvero b moltiplicato per se stesso n volte. In particolare si definisce

b0 = 1
ovvero, qualunque base elevata alla potenza 0 assume il valore 1.

Inoltre si definiscono le potenze negative come le potenze del reciproco della base, ovvero

 -n   1
b   = bn

Alcuni esempi di elevamento a potenza sono i seguenti:

     2
  3 3 = 3 ×3 = 9
 5 3= 5× 5× 5 = 125
  2 =2  2× 2× 2 = 8
5  4  = 4× 4 = 16
1= 1 × 1×1 1× 1× 1 = 1
      141 = 14
      270 = 27
       7 0= 1
  -3  -312 =11
 2- 2= 231-= 8 =1-0,125
10   = 102 = 100 = 0,01
Per facilitare i calcoli illustrati nelle pagine seguenti, nella tab. 1.1 sono riportate alcune potenze delle basi 2 e 10.
Potenza---Valore-|Potenza---------Valore-|
2-5------0,03125-|10- 5----------0,000-01-|
2-4      0,0625 |10- 4           0,0001 |
2--32       0,125 |10-- 3 2            0,001 |
2-1        0,25 |10- 1             0,01 |
220          0,51 |11000                0,11 |
21            2 |101                 10 |
223            4 |1023                100 |
224           186 |11004              110000000 |
25           32 |105             100000 |
26           64 |106            1000000 |
278          128 |1078           10000000 |
229          255162 |11009         1100000000000000000 |
210         1024 |1010       10000000000 |
211         2048 |1011       100000000000 |
212---------4096--1012------1000000000000--

Tabella 1.1: Alcune potenze del 2 e del 10.

1.3.1.2 I numeri naturali

I numeri naturali N sono i numeri interi senza segno, come 0, 1, 2, 3, ... la cui rappresentazione, nel sistema di numerazione decimale, può essere espressa come

n sum -1
    di× 10i = dn-1× 10n-1 + ...+ d2× 102 + d1 ×101 + d0× 100
 i=0

dove n è il numero di cifre di cui si compone il valore decimale, di sono le cifre che lo costituiscono e 10i i pesi ad esse associati. Poiché i pesi hanno base 10, si parla di sistema di numerazione decimale. Dunque, ad esempio, nel sistema di numerazione decimale, il numero 7345, costituito da 4 cifre, è “pesato” nel modo seguente:

      3    2   1    0
pesi  10   10   10   10
cifre   7    3   4    5
Questo significa che la cifra 7 ha un peso 10 volte superiore a quello della cifra 3, che a sua volta ha un peso dieci volte superiore rispetto a quello della cifra 4, la quale ha un peso dieci volte superiore rispetto a quello della cifra 5. Quindi si può scrivere:
7 × 103 + 3 × 102 + 4 × 101 + 5 × 100 = 7345
In questo modo, si possono definire altri sistemi di numerazione, semplicemente cambiando la base di riferimento. Scegliendo come base il valore più piccolo possibile, cioè 2, si ottiene il sistema di numerazione binario, con base 8 si ha il sistema di numerazione ottale, con base 16 si ottiene il sistema di numerazione esadecimale, ... Poiché, come accennato in precedenza, in un elaboratore le informazioni si basano soltanto su due valori possibili (due cifre: “0” e “1”), la rappresentazione di questi avviene per mezzo del sistema di numerazione binario. La posizione occupata da una cifra all’interno di un numero binario è dunque pesata, anziché da una potenza di 10 (come avviene nel sistema di numerazione decimale), da una potenza di 2, cioè un numero binario può essere espresso come

n-1
 sum  b × 2i = b   ×2n- 1 + ...+ b × 22 + b × 21 + b × 20
i=0 i       n-1             2        1       0

dove n è il numero di cifre di cui si compone il valore binario, bi sono le cifre che lo costituiscono e 2i i pesi ad esse associati. Pertanto il valore binario 1101, costituito da 4 cifre, corrisponde al valore decimale 13, infatti

pesi  23  22  21  20
cifre   1   1  0   1
1 × 23 + 1 × 22 + 0 × 21 + 1 × 20 = 13
Quindi si può scrivere 11012 = 1310.3

Da quanto illustrato, segue che un numero binario di n cifre, può rappresentare valori interi senza segno (numeri naturali) da 0 a 2n - 1.

Il sistema di numerazione binario è piuttosto scomodo in quanto, disponendo soltanto dei simboli “0” e “1”, necessita di molte cifre per rappresentare un valore. Per questo vengono utilizzate altre rappresentazioni numeriche che raggruppano più cifre binarie in un’unica cifra. Ne sono un esempio i numeri esadecimali (sistema di numerazione a base 16) che raggruppano 4 cifre binarie in ogni cifra esadecimale. Tale sistema di numerazione si basa sull’utilizzo di 16 simboli: “0”, “1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”, “A”, “B”, “C”, “D”, “E”, “F”. I simboli alfabetici da “A” ad “F” rappresentano i valori decimali che vanno da 10 a 15.4

Dunque il valore binario 100111012 può essere rappresentato come valore esadecimale 9D 16, infatti le prime quattro cifre binarie corrispondono al valore esadecimale “9”, 10012 = 910 = 916, e il secondo gruppo composto dalle seconde ed ultime 4 cifre binarie corrisponde al valore esadecimale “D”, 11012 = 1310 = D16. Ragionando come in precedenza, si può avere riprova di quanto affermato:

pesi  161  160    27  26  25  24  23  22  21  20
cifre   9   D       1   0  0   1   1   1  0   1
9 × 161 + 13 × 160 = 157
1 × 27 + 0 × 26 + 0 × 25 + 1 × 24 + 1 × 23 + 1 × 22 + 0 × 21 + 1 × 20 = 157

In genere i numeri esadecimali sono rappresentati anche posponendo il pedice “H” al numero considerato. Pertanto le scritture 9D16 e 9DH sono equivalenti.

Per convertire un numero decimale nel corrispondente valore binario si può utilizzare il metodo delle divisioni successive. Un valore infatti, se diviso per la base del sistema di numerazione dà come resto il valore della cifra meno significativa del numero. Quindi per trovare il valore binario corrispondente al valore decimale 2510 si può operare come segue
Operazione---Risultato--Resto--
  25/2       12       1
  12/2        6       0
  6/2         3       0
  3/2         1       1
  1/2         0       1
Il meccanismo delle divisioni, può essere arrestato quando il quoziente ottenuto è 0. Quindi, cosiderando le cifre ottenute dai resti, lette nell’ordine opposto a quello nel quale sono state ottenute, si può scrivere
2510 = 110012
1.3.1.3 I numeri interi negativi

Per quanto riguarda i numeri interi negativi, si introduce l’operazione di complemento. Il complemento è l’operazione che fornisce il valore complementare del numero considerato, rispetto ad un numero con le stesse cifre di quello in oggetto poste ad un valore prefissato. Ad esempio, nel sistema di numerazione decimale, il complemento a 9 del numero 324 su 4 cifre (0 324) è 9675, infatti il complementare di 324 rispetto a 9999 è 9675 (9 999 - 324 = 9675).

Valore decimale Complemento a 9 Valore di riferimento
  0 324         9 675           9 999
Si tratta praticamente di un’operazione di sottrazione. Nel sistema di numerazione binario si parla in maniera equivalente di complemento ad 1. Ad esempio, il complemento ad 1 del numero 000100102 è 111011012, che si può ottenere sostituendo tutte le cifre “0” con la cifra “1” e viceversa (questo lo si può ottenere applicando ad ogni singola cifra binaria l’operazione di negazione logica, v. sez. 1.3.4).
Valore binario Complemento a 1 Valore di riferimento
00010010     1110 1101        11111111
Si può parlare anche di complemento a b, dove b è la base del sistema di numerazione considerato, ovvero per il sistema decimale è il complemento a 10, mentre per il sistema di numerazione binario è il complemento a 2. In tal senso si ricerca il complementare di un numero rispetto ad un valore composto dallo stesso numero di cifre poste a b - 1, a cui si aggiunge 1. Ad esempio, il complemento a 10 su 4 cifre del numero decimale 72 è 9 938 poiché (9999 + 1) - 72 = 10000 - 72 = 9938. Il complemento a b si può ottenere calcolando il complemento a b - 1 e quindi aggiungendo 1 al risultato. Ad esempio, il complemento a 2 del numero 000100102 (su 8 cifre) è 111011102, ovvero 111011012 + 1.
Valore decimale Complemento a 10 Valore di riferimento
  0 072          9938            10000
Valore binario Complemento a 2 Valore di riferimento
00010010     1110 1110        100000000
Dal punto di vista matematico, la sottrazione tra due numeri A e B si può ottenere con l’operazione di somma tra A ed il complemento a b di B, scartando l’eventuale cifra più significativa in più rispetto a quelle tra le quali viene effettuato il calcolo. Ad esempio, si supponga di voler calcolare 43 - 26, senza utilizzare l’operazione di sottrazione. Il complemento a 10 di 26 (ad esempio su 3 cifre) è 974, quindi, applicando quanto affermato precedentemente si ha 43 + 974 = 1017. Il risultato è composto da più di 3 cifre, quindi le cifre in più (quelle più significative) vengono scartate, ottenendo 017, cioè 17, proprio il risultato della sottrazione. Analogamente in binario (su 8 cifre) 001010112 - 000110102 si riduce a 001000112 + 111001102 = 1000100012, quindi, scartando la cifra più significativa (la nona, quella più a sinistra), si ha 000100012, cioè 100012. Questo procedimento, che può apparire complicato, permette di dimenticarsi completamente dell’operazione di sottrazione nel sistema di numerazione binario: infatti il complemento a 1 si ottiene sostituendo le cifre 0 con 1 e le cifre 1 con 0 ed il complemento a 2 lo si può ottenere aggiungendo 1 al complemento a 1.

Dunque, un numero negativo -n può essere praticamente rappresentato dal complemento a b del numero n. Quindi, nel sistema di numerazione binario, i numeri negativi sono rappresentati con il complemento a 2 del corrispondente numero senza segno. Ad esempio, il valore -1510 viene rappresentato come il complemento a 2 di 1510, ovvero, considerando 8 cifre binarie, 1510 = 000011112, quindi -1510 = 111100012. In particolare, il numero -1 è rappresentato su 8 cifre come 111111112 ovvero è il complemento a 2 di 000000012.

Da quanto illustrato, segue che un numero binario di n cifre può rappresentare, in complemento a 2, valori interi con segno, cioè sia positivi che negativi, che vanno da -2n-1 a 2n-1 - 1.

I valori negativi, ovvero rappresentati in complemento a 2, sono riconoscibili dal fatto che la prima cifra binaria ha vaolore 1.

Il tentativo di memorizzare su n cifre, su un computer, un valore numerico (con segno) maggiore di 2n-1 - 1 o minore di -2n-1 genera un errore di overflow: il numero richiederebbe un numero di cifre binarie maggiore per poter essere rappresentato.

1.3.1.4 I numeri con parte non intera

I numeri che contengono una parte non intera sono rappresentati da due gruppi di cifre, separati da una virgola: il gruppo di cifre alla sinistra della virgola rappresenta la parte intera del numero, mentre quella a destra è la parte non intera. Ad esempio, il numero 352,74 è composto dalla parte intera 352 e dalla parte non intera 0,74 ed i pesi associati alle varie cifre sono i seguenti

pesi  102  101  100     10- 1 10-2
cifre   3    5   2   ,   7     4
La rappresentazione di un valore secondo il sistema di numerazione decimale è la seguente

n- sum 1      i          n-1           0        -1         -2            - m
  di× 10 = dn-1× 10   +...+d0 × 10 +d-1× 10  +d -2× 10  +...+d -m × 10
i=-m

mentre nel sistema di numerazione binario è

n- sum 1      i         n-1           0        - 1        -2             -m
   bi× 2 = bn-1× 2   + ...+ b0× 2 + b-1 ×2   + b-2× 2  + ...+ b-m × 2
i=-m

dove n è il numero di cifre di cui si compone la parte intera, m è il numero di cifre di cui si compone la parte non intera, di sono le cifre che compongono il numero decimale e bi quelle che compongono il numero binario, con i relativi pesi (10i e 2i ).

La parte non intera del numero è costituita dalle cifre che seguono la virgola, ovvero dalle cifre con pedice negativo, d-1, d-2, ... per i valori decimali e b-1, b-2, ... per quelli binari.

Per convertire la parte non intera di un numero decimale nel corrispondente valore binario, si può procedere con moltiplicazioni successive. Infatti, moltiplicando la parte non intera per la base del sistema di numerazione, si ottiene, come parte intera, la cifra più significativa della parte non intera, cioè, con riferimento al simbolismo utilizzato precedentemente, d-1 o b-1. Ad esempio, il valore decimale 0,853 moltiplicato per la base (10) dà come risultato 8,53 ovvero 8 è la cifra più significativa della parte non intera. Moltiplicando la nuova parte non intera (0,53) nuovamente per la base si ottiene 5,3 che fornisce come parte intera la seconda cifra non intera 5. Procedendo ulteriormente con le moltiplicazioni si ottengono, una dopo l’atra, tutte le cifre della parte non intera. Lo stesso ragionamento può essere applicato con un’altra base. Quindi, per trovare il valore binario corrispondente al valore decimale 18,3125 si può operare come segue: si considera innanzi tutto la parte intera, 18, a cui si applica il procedimento descritto in precedenza ottenendo 1810 = 100102. Poi si considera la sola parte non intera (18,3125 - 18 = 0,3125) e si applicano le moltiplicazioni successive appena descritte, con base 2

Operazione---Risultato--Parte-intera--Parte-non-intera--
0,3125× 2    0,625        0           0,625
0,625 × 2     1,25         1            0,25
0,25× 2      0,5         0            0,5
 0,5 × 2       1          1             0
Il meccanismo delle moltiplicazioni, può essere arrestato quando la parte non intera si è ridotta a 0. Quindi, cosiderando le cifre ottenute come parti intere dei risultati parziali, prese nell’ordine nel quale sono state ottenute con le operazioni, si può scrivere
0, 312510 = 0,01012
per cui
18,312510 = 10010,01012
Infatti
     4   3   2   1  0      -1   -2   -3  - 4
pesi  2   2   2   2   2     2    2    2    2
cifre   1   0  0   1   0  ,   0    1    0   1
1×24+0×23+0×22+1×21+0×20+0×2-1+1×2-2+0×2-3+1×2-4 = 18,3125
Si noti che non tutti i numeri reali R sono rappresentabili all’interno di un computer. Ad esempio i numeri irrazionali, come p  ~~ 3,1415...10, oppure i periodici (composti da un numero infinito di cifre dopo la virgola) come 1/310 = 0,310  ~~ 0,33333...10, non sono ovviamente memorizzabili avendo a disposizione un numero finito di celle di memoria (tali numeri possono essere approssimati, troncandoli a partire da una determinata cifra dopo la virgola). Inoltre, poiché il numero di cifre dopo la virgola varia in funzione del sistema di numerazione utilizzato (ad esempio 0,210 = 0,00112  ~~ 0,00110011...2), anche numeri decimali con un numero finito di cifre dopo la virgola possono non essere rappresentabili esattamente nel sistema di numerazione binario.

Qualunque numero (tranne il valore 0), può essere sempre rappresentato da un valore con parte intera non nulla ed inferiore alla base, moltiplicato per un’opportuna potenza della base: ad esempio 346,57 = 3,4657 × 102, Questa operazione (moltiplicazione del valore per un’opportuna potenza della base) è detta normalizzazione. La parte non intera che precede il simbolo di moltiplicazione, è detta mantissa o fraction (nell’esempio 4657) ed il valore che appare in alto a destra della base è detto esponente o caratterisitica (nell’esempio precedente, il valore 2). Quindi in notazione binaria (base 2) sarà sempre possibile per mezzo della normalizzazione, tranne nel caso del valore 0, rappresentare un valore per mezzo di determinati valori di mantissa ed esponente, tali che la sua parte intera risulti 1. Pertanto un numero non intero può essere rappresentato all’interno del computer mediante una coppia di valori di mantissa ed esponente. Poiché la virgola, durante l’operazione di normalizzazione e denormalizzazione5 subisce degli spostamenti verso sinistra o verso destra rispetto alle varie cifre che compongono il numero, tale tipo di rappresentazione viene detta anche rappresentazione in virgola mobile (floating point).

Lo standard IEEE 754 è quello utilizzato per la rappresentazione dei valori numerici in virgola mobile (normalizzati) nei computer. Tale standard prevede due tipi di rappresentazioni: single precision (precisione singola) e double precision (precisione doppia), che si differenziano dal numero di bit6 necessari per la rappresentazione dei valori stessi: entrambi utilizzano la rappresentazione dei valori della mantissa e dell’esponente come se fossero dei numeri naturali, ed un bit per la rappresentazione del segno. In particolare l’esponente è memorizzato come un numero naturale, ma per tener conto del fatto che esso potrebbe assumere anche valori negativi, è necessario sommarlo preventivamente ad un valore, detto bias, che rappresenta lo 0. In definitiva, il valore decimale corrispondente alla rappresentazione di un numero secondo lo standard IEEE 754 è dato da

(-1)S × 2E-bias× (1+ M  × 2- bM )

dove S è il valore del bit di segno, E è il valore dell’esponente, M è il valore della mantissa e bM è il numero di bit utilizzati per la rappresentazione della mantissa.

Alcuni valori assunti dalla mantissa e dall’esponente, assumono un particolare significato, riportato nella tab. 1.2.


Segno--Esponente----Mantissa-------Significato--------------------------|
|0----tutti i bit a-0-tutti i bit a 0-0--------------------------------|
|1    tutti i bit a 0 tutti i bit a 0 - 0                              |
|0    tutti i bit a 0 non tutti i bit a 0 Positive Denormalized Real: 0,M ×21-bias
|1    tutti i bit a 0 non tutti i bit a 0 Negative Denormalized Real:-0,M ×21-bias|
|01    ttututttii i i b bitit a a 11 tututttiti i i b biitt a a 0 0  oo -  oo                             |
|0    tutti i bit a 1 non tutti i bit a 0 Numero non valido (NaN -Not a Number)
-1----tutti i bit a-1-non-tutti i bit a 0-Numero-non-valido-(NaN--Not a-Number)

Tabella 1.2: Particolari significati attribuiti alla rappresentazione dei numeri floating point.

Da quanto evidenziato si hanno due possibili tipi di errori diversi nella gestione dei numeri non interi: il tentativo di memorizzare un numero il cui valore assoluto è inferiore a 2-bias+1 produce un errore di underflow, mentre quello di memorizzare un numero il cui valore assoluto è maggiore di (2 - 2-bM) × 2bias (dove bM è il numero di bit utilizzati per memorizzare la mantissa) genera un errore di overflow. L’errore di underflow sta a significare il fatto che sarebbero necessari più bit per rappresentare un esponente molto piccolo (ma in valore assoluto molto grande). Infatti, si considerino i valori sempre più piccoli, che si approssimano sempre di più allo 0: 0,110 = 1 × 10-1, 0,0110 = 1 × 10-2, 0, 00110 = 1 × 10-3, ... per la rappresentazione dei quali sono necessari esponenti sempre più piccoli (-1, -2, -3, ...), ma in valore assoluto sempre più grandi (1, 2, 3, ...). Oltre una certa precisione il valore dell’esponente non può essere rappresentato su 8 o 11 bit.