A Rappresent Num
A Rappresent Num
Fondamenti di Informatica
Copyright © 2021 Vincenzo Grassi ([Link]@[Link]) – Università degli studi di Roma “Tor Vergata”
Questa dispensa fa parte dei materiali messi a disposizione nel corso di Fondamenti di Informatica,
che è il primo della serie di corsi a contenuto informatico che incontrerete nel vostro corso di studi. In
questa prefazione, cercherò di dare alcune indicazioni generali sui contenuti e sulla impostazione che
verrà adottata nell’insegnamento di questo corso.
L’informatica, come probabilmente potete immaginare, è ormai una disciplina che affronta e tenta di
risolvere una ampia gamma di problematiche, anche di notevole complessità. Di tutto questo, voi
probabilmente già avete sperimentato gli "effetti finali": la guida di un'automobile, l'effettuazione di un
servizio nella pubblica amministrazione, l'ascolto di un brano musicale, una previsione meteorologica,
la visione di un film, un intervento chirurgico, ... sono tutte attività dietro le quali possiamo trovare, a
volte in modo inaspettato, l'uso anche massiccio di strumenti e metodologie informatiche.
Data la complessità della disciplina, chi progetta un primo corso che si addentra in essa deve
affrontare il classico problema della chiave di lettura da usare per definire un primo percorso di studio
e, soprattutto, "da dove iniziare".
Riguardo il primo punto (la chiave di lettura) questo corso presenta una visione dell'informatica come
insieme di metodologie e tecnologie per "risolvere problemi con l'ausilio di macchine". Per
raggiungere questo obiettivo, i punti cardine su cui questo corso insisterà sono due:
- definizione di una RAPPRESENTAZIONE degli elementi del problema;
- definizione di un METODO RISOLUTIVO.
Per "rappresentazione" si intende la definizione di un "modello astratto" di un qualche frammento di
realtà di interesse, dove l'astrazione consiste fondamentalmente nella evidenziazione di aspetti
salienti della realtà ai fini della soluzione del problema di interesse, tralasciando aspetti marginali.
Per "metodo risolutivo" si intende una sequenza di passi, eseguibili da una macchina, che agiscono
sulla rappresentazione per arrivare ad una soluzione in modo simbolico (cioè definita in termini del
modello) del problema. Si noti che "eseguibili da una macchina" significa che questi passi non devono
prevedere nessun intervento "creativo" da parte della macchina stessa, ma solo una applicazione
pedissequa dei passi specificati. Da questo punto di vista, la "macchina" potrebbe anche essere, al
limite, un essere umano a cui si chiede un ruolo puramente esecutivo. Però, visto che i problemi di
interesse richiedono di solito l'esecuzione di un notevole numero di passi (anche miliardi), siamo più
interessati a macchine propriamente dette. In questo caso, un aspetto fondamentale per poterle
utilizzare effettivamente consiste nella definizione di un "linguaggio" appropriato, con cui sia possibile
specificare alla macchina sia la rappresentazione adottata che la sequenza di passi che costituiscono
il metodo risolutivo. Ovviamente, tutte queste tematiche coinvolgono problematiche di notevole
complessità, il cui studio e approfondimento va ben oltre i limiti (piuttosto ristretti) di questo singolo
corso.
Questo ci introduce al secondo punto accennato sopra, cioè "da dove iniziare". Questo corso,
seguendo un percorso ormai consolidato, privilegia un approccio che possiamo chiamare "linguistico":
l'introduzione all'informatica avviene tramite l'introduzione ad un linguaggio con le caratteristiche
specificate sopra. Come tutti i linguaggi, anche questo sarà caratterizzato da un suo lessico (insieme
di termini), sintassi (insieme di regole per comporre termini in modo grammaticalmente corretto) e
semantica (regole per assegnare un significato a frasi sintatticamente corrette). Quindi obiettivo
fondamentale di questo corso è l'apprendimento di (un sottoinsieme di, per ragioni di spazio) questi
tre elementi base di un particolare linguaggio, e questo sarà l'oggetto delle verifiche intermedie e
finali: come per tutti i linguaggi, verrà verificata la capacità di comprendere "frasi" scritte in questo
linguaggio, e di scriverne altre. Tutti questi elementi verranno sempre inquadrati nell'ottica dei due
punti cardine delineati sopra, che non dovrebbero mai essere persi di vista: questo linguaggio serve
per comunicare ad una macchina un modo di rappresentare un problema e un modo di risolverlo.
Questo corso non presuppone nessuna conoscenza pregressa di tipo informatico, ma solo le
conoscenze matematiche proprie dei corsi che precedono o affiancano questo nel piano di studi. E'
quindi calibrato su questi presupposti: chi ritenesse di avere già in parte conoscenze informatiche è
pregato di fare un esercizio di umiltà e di seguire comunque il percorso di studio consigliato.
2
Indice
3
Capitolo 1 - Rappresentazione di numeri interi
da: J.-M. Levy-Leblond “La scienza è davvero universale?”, Le Monde Diplomatique, Maggio 2006, pp. 24-25
1. Concetti generali
Sia S = {s0, s1, …, sk} un insieme finito di simboli.
Sia S* l’insieme di tutte le sequenze finite costruibili usando simboli appartenenti a S, esclusa la
sequenza vuota.
Si noti che S* è un insieme infinito.
4
Esempio
S = {a}
S* = {a, aa, aaa, aaaa, aaaaa, … };
oppure:
S = {a, b}
S* = {a, b, aa, ab, ba, bb, aaa, aab, aba, baa, abb, … }
Fine esempio
Sia N l’insieme dei numeri naturali {0, 1, 2, 3, … }. Una rappresentazione di N è una funzione
iniettiva
r : N --> S*
che possiede una funzione inversa (interpretazione o decodifica)
Á : S* --> N
tale che, data sÎS*,
⎧n ∈ N se r(n) = σ
Á(s) = ⎨
⎩ indefinito altrimenti
2. Rappresentazione posizionale
€ Sia B un numero intero ≥2. Una rappresentazione posizionale in base B viene definita in questo
modo:
S = {s , s , …, s }
B 0 1 B-1
Esempio
La rappresentazione in base 10 che siamo abituati ad usare non è altro che un caso particolare
della rappresentazione appena definita, con B=10, S10 = {0, 1, 2, …, 9}. Infatti, data una sequenza
appartenente a S10*, [Link]. 343, questa viene interpretata come rappresentazione del valore numerico
2 1 0
3·10 + 4·10 + 3·10 .
Fine esempio
5
Si noti che una stessa sequenza di simboli rappresenta, in generale, valori numerici diversi al
variare di B; così, la sequenza 101 rappresenta i seguenti valori numerici (espressi nella usuale
notazione in base 10):
se B=2, rappresenta il valore 1·22 + 0·21 + 1·20 = (5)10
2 1 0
se B=3, rappresenta il valore 1·3 + 0·3 + 1·3 = (10)10
Potenza k-esima
Il valore Bk in base B è rappresentato dalla sequenza (ck ck-1 ck-2 … c0)B, con ck=1 e ci=0,
6
4. Rappresentazione con numero finito di cifre
Supponiamo di porre un limite massimo (pari ad h≥1) alla lunghezza delle sequenze di simboli
utilizzabili in una rappresentazione posizionale di N (da notare che questo è quanto succede
effettivamente nelle macchine che utilizziamo per eseguire calcoli numerici). Questo limite comporta
come conseguenza la possibilità di rappresentare soltanto un sottoinsieme finito dell’insieme N.
Indichiamo con N N questo sottoinsieme. In base al risultato della Sezione 3, si ha:
B,h ⊂
NB,h = {n | nÎN, 0 ≤ n ≤ Bh - 1}
Utilizzare una rappresentazione di N usando un numero finito di cifre porta come conseguenza
che non sempre gli algoritmi che utilizziamo per calcolare le operazioni aritmetiche restituiscono il
risultato corretto. Ad esempio, supponiamo che AlgSomma(.,.) indichi un algoritmo per il calcolo della
somma tra interi (ad esempio, potrebbe essere l’usuale algoritmo che ci è stato insegnato durante la
scuola elementare, basato sulla somma cifra per cifra da destra a sinistra e sulla regola del riporto).
Questo algorimo si applica a due sequenze di simboli (aq-1 aq-2 … a0)B e (bs-1 bs-2 … b0)B e
restituisce come risultato una nuova sequenza di simboli (ct-1 ct-2 … c0)B, con t≥max{q, s}, tale che
ÁN(aq-1 aq-2 … a0)B + ÁN(bs-1 bs-2 … b0)B = ÁN(ct-1 ct-2 … c0)B
Nel caso che stiamo considerando di rappresentazione con un numero finito h di cifre,
AlgSomma(.,.) deve necessariamente essere modificato, dando luogo al seguente algoritmo (si noti
che, per il vincolo che ci siamo posti sulla rappresentazione, deve essere q≤h e s≤h):
AlgSommaB,h(.,.):
acquisisci (aq-1 aq-2 … a0)B e (bs-1 bs-2 … b0)B;
determina (ct-1 ct-2 … c0)B usando AlgSomma(.,.);
se t>h, elimina le cifre ct-1 ct-2 … ch;
restituisci come risultato la sequenza di cifre restanti.
In altre parole, AlgSommaB,h(.,.) tronca alla h-esima cifra il risultato della somma. Questa
operazione di troncamento può ovviamente portare a situazioni di errore. Più precisamente, l’errore si
verifica se ÁN(aq-1 aq-2 … a0)B + ÁN(bs-1 bs-2 … b0)B ÏNB,h. Questo tipo di errore viene detto
Esempio
Assumiamo B=10 e h=3;
7
Nel secondo caso, il risultato corretto sarebbe stato 1113; l’algoritmo produce un risultato
scorretto perchè 1113 rappresenta un valore numerico che va al di là dei limiti della rappresentazione
scelta; infatti, con B=10 e h=3 il massimo intero rappresentabile è pari a 103 - 1 = 999.
Fine esempio
dato xÎZ,
⎧ Bh
⎪ rB (x) se0 ≤ x <
rc(x) = ⎨ 2
h
B
⎪rB ( Bh - x ) se - ≤ x <0
⎩ 2
Da questa definizione, risulta evidente che si riesce a rappresentare soltanto il sottoinsieme
⎡ Bh Bh ⎞
finito di Z costituito dai numeri appartenenti all’intervallo - ⎟
⎢⎣ 2 ,+ 2 ⎠ (questa è, di nuovo, una
conseguenza dell’aver posto un limite al numero di cifre utilizzabili). In maniera informale, l’idea alla
base di questa rappresentazione è quella di suddividere l’intervallo dei naturali [0, Bh-1] (ovvero
l’insieme NB,h) in due metà, e di utilizzarne la prima metà per rappresentare i relativi appartenenti
8
⎡ Bh ⎞ ⎡ Bh ⎤
all’intervallo 0, + ⎟ , e la seconda metà per rappresentare l’intervallo dei relativi - ,-1 (vedi
⎢⎣ 2 ⎠ ⎢⎣ 2 ⎥⎦
Figura 1).
h h
- B
B
2 0 2
Z
h
B
0 h
2 B -1
N
Figura 1
Esempio
Consideriamo il caso B=2, h=3; si possono quindi rappresentare gli interi relativi appartenenti
all’intervallo [-4, +3]; questi valori verranno rappresentati utilizzando le rappresentazioni, definite dalla
funzione rB, dell’intervallo dei naturali [0, 7]. Si ha quindi (per maggiore chiarezza, utilizziamo sempre
una notazione a tre cifre, incluse quindi le cifre 0 non significative (cioè quelle più a sinistra)):
rB(0) = 000
rB(1) = 001
rB(2) = 010
rB(3) = 011
rB(4) = 100
rB(5) = 101
rB(6) = 110
rB(7) = 111
Delle otto sequenze di simboli così ottenute, le prime quattro (cioè 000, 001, 010, 011) vengono
utilizzate per rappresentare l’intervallo [0, +3], e le seconde quattro (cioè 100, 101, 110, 111) per
rappresentare l’intervallo [-4, -1], nel seguente modo:
rc(0) = rB(0) = 000
rc(1) = rB(1) = 001
rc(2) = rB(2) = 010
rc(3) = rB(3) = 011
Analogamente, con B=10 e h=2, l’intervallo dei relativi [-50, +49] viene rappresentato tramite
l’intervallo dei naturali [0, 99], nel seguente modo:
9
rc(0) = rB(0) = 00
rc(1) = rB(1) = 01
rc(2) = rB(2) = 02
r (3) = r (3) = 03
c B
…
r (47) = r (47) = 47
c B
rc(48) = rB(48) = 48
rc(49) = rB(49) = 49
…
rc(-2) = rB(102 - |-2|) = 98
Fine esempio
Esempio
Consideriamo il caso B=3, h=3. Le sequenze di simboli utilizzabili per la rappresentazione sono
quindi: 000, 001, 002, 010, 011, 012, 020, 021, 022, 100, …, 212, 220, 221, 222; secondo la funzione
di interpretazione ÁN, queste sequenze rappresentano l’intervallo dei naturali: 0, 1, 2, 3, 4, 5, 6, 7, 8,
9, …, 23, 24, 25, 26. Interpretate secondo alla funzione ÁZ (ovvero, come rappresentazione in
complemento di numeri relativi) queste stesse sequenze rappresentano i seguenti valori numerici:
Á (000) = Á (000) = 0, Á (001) = Á (001) = 1, …, Á (111) = Á (111) = 13, Á (112) = -(33 -
Z N Z N Z N Z
3 3
Á (112)) = -13, …, Á (221) = -(3 - Á (221)) = -2, Á (222) = -(3 - Á (222)) = -1. (Quindi, l’intervallo
N Z N Z N
dei relativi rappresentabile è [-13, +13]).
Se consideriamo invece il caso B=10, h=2, le sequenze di due cifre decimali 00, 01, 02, …, 97,
98, 99 vengono interpretate come:
10
ÁZ(00) = ÁN(00) = 0, ÁZ(01) = ÁN(01) = 1, …, ÁZ(49) = ÁN(49) = 49, ÁZ(50) = -(102 - ÁN(50))
= -50, …, ÁZ(98) = -(102 - ÁN(98)) = -2, ÁZ(99) = -(102 - ÁN(99)) = -1. (Quindi, l’intervallo dei relativi
Esempio
Consideriamo B=2 e h=4. L’intervallo dei relativi rappresentabile è quindi [-8, +7]. Consideriamo
i seguenti numeri relativi (espressi nella usuale base 10): 2, 3, 4, 7, -3, -4, -1. Le loro
rappresentazioni, nella notazione in complemento in base 2, sono:
rc(2) = 0010, rc(3) = 0011, rc(4) = 0100, rc(7) = 0111, rc(-3) = 1101, rc(-4) = 1100, rc(-1) =
1111.
Consideriamo ora le seguenti operazioni di somma tra i numeri sopra elencati:
2 + 4, 3 + 3, 3 + (-3), 4 + (-3), 7 + (-1), -4 + (-3)
Per eseguirle utilizziamo l’algoritmo AlgSomma2,4(.,.); il lettore è invitato a verificare che i
risultati forniti nel seguito sono effettivamente quelli ottenuti applicando questo algoritmo (usando
l’aritmetica in base 2!):
2 + 4 ==> AlgSomma2,4(0010, 0100) = 0110
il numero rappresentato da 0110 è Á (0110) = +6, quindi il risultato
Z
calcolato è corretto
3 + 3 ==> AlgSomma (0011, 0011) = 0110
2,4
il numero rappresentato da 0110 è Á (0110) = +6, quindi il risultato
Z
calcolato è corretto
3 + (-3) ==> AlgSomma (0011, 1101) = 0000
2,4
il numero rappresentato da 0000 è Á (0000) = 0, quindi il risultato
Z
calcolato è corretto
4 + (-3) ==> AlgSomma2,4(0100, 1101) = 0001
il numero rappresentato da 0001 è ÁZ(0001) = +1, quindi il risultato
calcolato è corretto
7 + (-1) ==> AlgSomma2,4(0111, 1111) = 0110
il numero rappresentato da 0110è Á (0110) = +6, quindi il risultato
Z
calcolato è corretto
11
-4 + (-3) ==> AlgSomma2,4(1100, 1101) = 1001
il numero rappresentato da 1001 è ÁZ(1001) = -7, quindi il risultato
calcolato è corretto
Fine esempio
ah-2 … a0) sia la sequenza di cifre che rappresenta n in base B; si ha allora:Bh-n = Bh-1 - n + 1 =
h-1 h-1 h-1
∑ (B-1)·Bi -∑ ai·Bi + 1 =∑ ((B-1)-ai)·Bi + 1
i=0 i=0 i=0
La complementazione si effettua quindi nel seguente modo:se (ah-1 ah-2 … a0) è la sequenza
di cifre che rappresenta un numero nÎZ, allora la sequenza di cifre che rappresenta Bh-n è calcolata
dall’algoritmo
ComplB,h(ah-1 ah-2 … a0) = AlgSommaB,h((bh-1 bh-2 … b0), (uh-1 uh-2 … u0)),
⎧1 se i= 0
con bi = (B-1) - ai, 0≤i≤h-1 ui = ⎨
⎩ 0 se 1≤ i≤ h -1
Esempio
Consideriamo il caso B=2, h=4, i seguenti numeri relativi: +5, -4, +1, e le loro rappresentazioni
in complemento date da rc(5) = 0101, rc(-4) = 1100, rc(1) = [Link] le seguenti
12
ÁZ (0100 ) = +4, quindi il risultato calcolato è corretto
è corretto.
Consideriamo ora il caso B=10, h=2, i seguenti numeri relativi: +25, -41, -12, e le loro
rappresentazioni in complemento date da rc(25) = 25, rc(-41) = 59, rc(-12) = 88.
è corretto;
-41 - (-12) ==> è calcolabile come -41 + (+12); la rappresentazione di +12 si determina come
Compl10,2(88) = AlgSomma10,2(11, 01) = 12; quindi -41 + (+12) si calcola
come AlgSomma10,2(59, 12) = 71; poichè Á°Z(71 ) = -29, il risultato calcolato
è corretto.
Fine esempio
Si noti che negli esempi appena fatti sulla esecuzione di operazioni aritmetiche usando la
rappresentazione in complemento, il risultato era sempre corretto perché rientrava nei limiti
dell’intervallo di rappresentazione. Se invece il risultato cade al di fuori di tale intervallo (cioè se è<-
Bh Bh
, oppure ≥ ), allora il risultato calcolato sarà ovviamente scorretto.
2 2
Esempio
Consideriamo il caso B=2, h=4. L’intervallo di rappresentazione è quindi [-8, +7]. Consideriamo
i seguenti numeri relativi: +5, +4, -6, -3. Questi numeri appartengono all’intervallo di rappresentazione,
e le loro rappresentazioni in complemento sono date da rc(+5) = 0101, rc(+4) = 0100, rc(-6) = 1010,
rc(-3) = 1101.
13
la funzione ÁZ(.); si ha quindi ÁZ(0111) = +7, che è evidentemente errato;
+5 - (-6) ==> si calcola come AlgSomma2,4(0101, Compl24(1010)) =
AlgSomma2,4(0101, 0110) = 1011; poiché stiamo utilizzando la
Analogamente, consideriamo B=10 e h=2, e i seguenti valori numerici: +38, -43, -21. Le loro
rappresentazioni in complemento sono: rc(+38) = 38, rc(-43) = 57, rc(-21) = 79. Consideriamo le
-43 - (-21) ==> si calcola come -43 + (+21), la rappresentazione di +21 si ottiene
complementando quella di -21: Compl10,2(79) = 21; quindi
AlgSomma10,2(57, 21) = 78; poiché stiamo utilizzando la rappresentazione in
complemento questo risultato viene interpretato tramite la funzione ÁZ(.); si
ha quindi ÁZ(78) = -22, che è evidentemente corretto;
-43 + (-21) ==> si calcola come AlgSomma10,2(57, 79) = 36; poiché stiamo utilizzando la
Fine esempio
6. Conversione di base
Data una rappresentazione posizionale in una certa base B', un problema interessante è quello
di determinare la rappresentazione dello stesso numero in una differente base B". In generale, il
problema vale qualunque siano le basi di partenza B' e di arrivo B", tuttavia per semplicità noi
considereremo solo il caso in cui B'=10. Quindi il problema che consideriamo è come convertire la
usuale rappresentazione decimale di un numero intero positivo nella rappresentazione dello stesso
numero in una base B≠10.
Sia n il valore del numero che intendiamo convertire. La sua rappresentazione in base B, tuttora
incognita, sarà una sequenza di cifre (cp cp-1 … c0), tale che:
• 0≤ ci≤B-1 i = 0, 1, …
p
i
• ∑ ci·B = n
i= 0
Il problema è quindi quello di determinare il valore esatto delle cifre ci. Iniziamo con la cifra
meno significativa c0. Si può facilmente dimostrare che c0 è pari al resto della divisione intera tra n e
14
n = cp·Bp + cp-1·Bp-1 + … + c1·B1 + c0
è facile rendersi conto che la divisione intera tra n e B darà come risultato:
• un quoziente pari a n' = cp·Bp-1 + cp-1·Bp-2 + … + c1
• un resto pari c0
Infatti, nella somma che corrisponde a n, riportata sopra, tutti gli addendi sono moltiplicati per
una potenza di B, e sono quindi divisibili esattamente per B, tranne c0, che non è divisibile per B
essendo per definizione 0≤ c0≤B-1.
E' facile ora rendersi conto che per determinare la successiva cifra della rappresentazione, c1,
si deve di nuovo ripetere il procedimento, dividendo per B il quoziente n' ottenuto al passo
precedente, e così via, ottenendo tutte le cifre della rappresentazione. Il procedimento si arresta
quando si ottiene un quoziente pari a zero. L'algoritmo di conversione di base di un numero n da base
10 a base B può quindi essere descritto in questo modo:
ConvInt(B, n) :
1. i <-- 0
2. finchè n>0, esegui in sequenza i comandi 3, 4, 5 (quando n=0, esegui 6):
3. ci <-- resto di n diviso B
4. n <-- quoziente di n diviso B
5. i <-- i+1
6. STOP: il risultato è (ci-1 ci-2 … c0)
Esempio
Consideriamo n=10, B=2; l'algoritmo esegue i seguenti passi:
• i=0: c0 = 0 (resto di 10/2) n = 5 (quoziente di 10/2)
• i=1: c1 = 1 (resto di 5/2) n = 2 (quoziente di 5/2)
• i=2: c2 = 0 (resto di 2/2) n = 1 (quoziente di 2/2)
• i=3: c3 = 1 (resto di 1/2) n = 0 (quoziente di 1/2)
• i=4: STOP
La rappresentazione in base 2 del numero 10 è quindi data da: 1010 (per verificare la
correttezza del risultato, si può applicare la funzione di interpretazione definita nel paragrafo 2).
Fine esempio
Esempio
Consideriamo n=33, B=5; l'algoritmo esegue i seguenti passi:
• i=0: c0 = 3 (resto di 33/5) n = 6 (quoziente di 33/5)
• i=1: c1 = 1 (resto di 6/5) n = 1 (quoziente di 6/5)
• i=2: c2 = 1 (resto di 1/5) n = 0 (quoziente di 1/5)
• i=3: STOP
La rappresentazione in base 5 del numero 33 è quindi data da: 113 (per verificare la
correttezza del risultato, si può applicare la funzione di interpretazione definita nel paragrafo 2).
15
Fine esempio
16
Capitolo 2 - Rappresentazione di numeri reali
1. Rappresentazione posizionale
La rappresentazione posizionale in base B di un numero reale x è una semplice
generalizzazione della rappresentazione posizionale per numeri interi. Essa è costituita da una
sequenza:
(ch-1 ch-2 … c0,c-1 c-2 … c-k)B ciÎ {0, 1, 2, …, B-1}
Esempio
Consideriamo B = 2, e la rappresentazione di un numero reale x data da (10,011)2.
2. Conversione di base
Dato un numero reale x, espresso nella usuale rappresentazione decimale, consideriamo il
problema di determinare la rappresentazione di x in una base B≠10.
Il numero x sarà costituito, in generale, da una parte intera i e da una parte frazionaria f:
x = i,f
con i numero intero e f tale che 0≤f<1.
Il problema della conversione di x in base B può quindi essere suddiviso nei due sottoproblemi
della conversione della parte intera i e della parte frazionaria f. Il primo sottoproblema è stato già
risolto (vedi cap. 1, paragr. 6), consideriamo quindi il secondo.
Il procedimento alla base dell'algoritmo è analogo al caso della conversione di un numero
intero. Anche in questo caso, possiamo affermare che la rappresentazione di f in base B, tuttora
incognita, sarà una sequenza di cifre (c-1 c-2 … c-k), tale che:
• 0≤ c ≤B-1 i = 0, 1, …
i
17
k
• ∑ c-i·B-i = f
i=1
Il problema è quindi quello di determinare il valore esatto delle cifre c-i. Iniziamo questa volta
con la cifra più significativa c-1. Si può facilmente verificare che c-1 è pari alla parte intera del prodotto
Esempio
Consideriamo x =22,625 e B=2; l'algoritmo esegue i seguenti passi:
parte intera:
• i=0: c0 = 0 (resto di 22/2) n = 11 (quoziente di 22/2)
• i=1: c1 = 1 (resto di 11/2) n = 5 (quoziente di 11/2)
• i=2: c2 = 1 (resto di 5/2) n = 2 (quoziente di 5/2)
• i=3: c3 = 0 (resto di 2/2) n = 1 (quoziente di 2/2)
• i=4: c4 = 1 (resto di 1/2) n = 0 (quoziente di 1/2)
18
• i=-1: c-1 = 1 (parte intera di 2·0,625) f = 0,25 (parte frazionaria di 2·0,625)
• i=-2: c-2 = 0 (parte intera di 2·0,25) f = 0,5 (parte frazionaria di 2·0,25)
• i=-3: c-3 = 1 (parte intera di 2·0,5) f = 0 (parte frazionaria di 2·0,5)
E' da notare però che, a differenza dell'algoritmo ConvInt(B, i), l'algoritmo ConvFraz(B, f) può
non terminare mai, continuando all'infinito a generare cifre della rappresentazione. Questo non è un
errore, ma corrisponde semplicemente al caso in cui la parte frazionaria di un numero reale è
rappresentata, in una certa base, da una sequenza infinita (periodica o aperiodica) di cifre. Si noti che
numeri che in una base sono rappresentati da parti frazionarie con un numero infinito di cifre, non è
detto che lo siano in altre basi.
Esempio
8
Consideriamo x = . La sua rappresentazione in base 10 è data da 0,8 con una parte
10
frazionaria finita. Se proviamo a determinare la rappresentazione di x in base B=2; l'algoritmo esegue
i seguenti passi:
• i=-1: c-1 = 1 (parte intera di 2·0,8) f = 0,6 (parte frazionaria di 2·0,8)
• i=-2: c-2 = 1 (parte intera di 2·0,6) f = 0,2 (parte frazionaria di 2·0,6)
• i=-3: c-3 = 0 (parte intera di 2·0,2) f = 0,4 (parte frazionaria di 2·0,2)
• i=-4: c-4 = 0 (parte intera di 2·0,4) f = 0,8 (parte frazionaria di 2·0,4)
• i= -5: c-5 = 1 (parte intera di 2·0,8) f = 0,6 (parte frazionaria di 2·0,8)
• i= -6: …
è facile rendersi conto che l'algoritmo continuerà a generare all'infinito la quadrupla 1100, senza mai
terminare.
2
Viceversa, consideriamo il numero y = , e consideriamo la sua rappresentazione in base
3
2
B=3. E' facile rendersi conto che essa è data da: 0,2 (infatti 2·3-1= ). E' altrettanto facile rendersi
3
conto che la rappresentazione di y in base 10 richiede invece una parte frazionaria infinita:
2
= 0,6666666…
3
Fine esempio
19
l'approssimazione sarà tanto più precisa quanto maggiore sarà il numero di cifre utilizzabili per la
parte frazionaria. Se indichiamo con k il numero massimo di cifre utilizzabili per rappresentare la parte
frazionaria, l'algoritmo ConvFraz(B, f) deve essere modificato come segue:
ConvFraz(B, k, f) :
1. i <-- 1
2. finchè f>0 e i≤k, esegui in sequenza i comandi 3, 4, 5
(quando f=0 oppure i>k, esegui 6):
3. c-i <-- parte intera di f moltiplicato per B
4. f <-- parte intera di f moltiplicato per B
5. i <-- i+1
6. STOP: il risultato è (c-1 c-2 … c-i+1)
Esempio
137
Consideriamo B = 10 e k=4. Consideriamo il numero x = . La sua rappresentazione in
4
base 10 è data da 34,25. Di conseguenza, si ha:
137
e(10, 4) = | x - appr(x, 10, 4) | = - 34,25 = 0
4
27
Consideriamo ora il numero y = . La sua rappresentazione in base 10 è data da
7
3,85714285714285… . Di conseguenza, si ha:
27
e(10, 4) = | y - appr(y, 10, 4) | = | - 3,8571 | = 0,00004285714285… ≤ 0,0001 = 10-4
7
Fine esempio
20
3.1 Rappresentazione in virgola fissa
Immaginiamo che lo spazio finito a disposizione sia costituito da un numero N di "caselle"
ognuna delle quali può contenere una cifra della rappresentazione. il modo più semplice di
rappresentare numeri reali in questo spazio è di utilizzare h caselle per la parte intera e le rimanenti
k= N-h caselle per rappresentare la parte frazionaria. uesta suddivisione automaticamente assegna
una posizione fissa (da cui il nome) alla virgola, che si troverà posizionata tra la h-esima e (h+1)-
esima casella (contando a partire da sinistra). In più, bisognerà considerare una casella aggiuntiva
per il segno.
Esempio
Consideriamo B = 10, N = 6, h = 3, e di conseguenza k = 6-3 = 3.
Lo spazio disponibile risulta organizzato come nella figura seguente, dove viene mostrata
l'utilizzazione di questo spazio per rappresentare il numero 12,05. Nella figura, la posizione della
virgola è rappresentata da una doppia linea verticale tra due caselle.
± 0 1 2 0 5 0
Fine esempio
+ 0 0 0 1 9 4 7 5
21
ma questo semplicemente sposta il problema, senza risolverlo alla radice. Una soluzione più
convincente richiede evidentemente di abbandonare (almeno concettualmente) l'idea di assegnare
una posizione fissa e immutabile alla virgola, e di adottare una rappresentazione in cui la virgola sia
"mobile".
Si noti che questa convenzione implica che |m| < 1. Da notare anche che l'assegnazione di una
posizione convenzionale prefissata alla virgola non è in contraddizione con la "mobilità" della virgola
stessa; questa è assicurata, in modo virtuale, dalla possibilità di variare il valore dell'esponente.
Esempio
Consideriamo B = 10, h = 2, e k = 3.
I numeri rappresentati come:
+ 1 0 2 + 0 2
+ 5 0 0 - 0 3
- 7 1 0 + 0 5
corrispondono ai seguenti valori numerici:
22
0,102 · 102 = 10,2
0,500 · 10-3 = 0,0005
-0,710 · 105 = -71000
Fine esempio
dove:
mmin è la minima mantissa (numero reale >0 e <1) rappresentabile in base B usando k cifre,
mmax è la massima mantissa (numero reale >0 e <1) rappresentabile in base B usando k cifre,
emin è il minimo esponente (intero negativo) rappresentabile in base B usando h cifre,
emax è il massimo esponente (intero positivo) rappresentabile in base B usando h cifre.
Si ha quindi:
-k
mmin = 0,00…01 = B (k-1 zeri dopo la virgola seguiti da un uno)
k
-i 1
mmax = 0,B-1 B-1 … B-1 = ∑ (B-1)·B = 1 - k
B
i=1
h
emax = B -1 (vedi cap. 1, paragr. 3)
h
emin = - (B -1)
-k h h 1 h
Quindi, xmin = B · B −B +1= B −(B +k−1) e xmax = (1 - k ) BB −1
B
Esempio
Consideriamo B = 10, h = 2, e k = 3.
xmin è rappresentato come:
23
+ 0 0 1 - 9 9
che corrisponde al valore:
xmin = 0,001·10-99 = 10-102
xmax è rappresentato come:
+ 9 9 9 + 9 9
che corrisponde al valore:
xmax = 0,999·1099
Se consideriamo invece B = 2, h = 2, e k = 3.
xmin è rappresentato come:
+ 0 0 1 - 1 1
che corrisponde al valore:
xmin = 0,001·(10)-11 = (10)-110
xmax è rappresentato come:
+ 1 1 1 + 1 1
che corrisponde al valore:
xmax = 0,111·(10)11
Si noti che in questo secondo esempio la base è B=2, quindi tutti i valori numerici sono
rappresentati in notazione binaria. Per conoscere il corrispondente valore espresso in notazione
decimale occorre convertire la rappresentazione, ottenendo così (riportiamo prima la notazione
binaria e poi il corrispettivo in decimale):
1
xmin = (10)-110 = 2-6 = = 0,015625
64
⎛ 1 1 1⎞ 7
xmax = 0,111·(10)11 = (2-1 +2-2 +2-3 )·23 = ⎜ + + ⎟ ·8 = ·8 = 7
⎝ 2 4 8⎠ 8
Fine esempio
E' ben noto che il sottoinsieme limitato dei reali formato dagli x tali che xmin ≤ | x | ≤ xmax
contiene un numero infinito di reali; di questi, in realtà, solo un sottoinsieme finito è rappresentabile
esattamente disponendo solo di k+h cifre per la rappresentazione. Infatti, disponendo di k+h caselle,
in ognuna delle quali si possono inserire B valori diversi (le cifre comprese tra 0 e B-1), si possono
rappresentare in tutto Bk+h numeri diversi. Proviamo a vedere più "da vicino" quali numeri sono
rappresentati, e come sono disposti sull'asse dei reali. Per semplicità, facciamo riferimento a un caso
concreto, considerando una rappresentazione con B = 10, h = 2, e k = 3. I soli numeri rappresentabili
in prossimità dello zero sono quelli esplicitamente indicati nella figura seguente:
24
0 -99 -99 -99 -99
0,001⋅10 0,002⋅10 0,003⋅10 0,999⋅10
-99
0,001⋅10
Come si può notare, questi primi numeri sono spaziati uniformemente, con ampiezza dello spazio tra
-102
essi pari a 10 . Andando "avanti" lungo l'intervallo, si può però notare che la spaziatura tra numeri
32
consecutivi inizia a crescere. Ecco ad esempio quale è la situazione in prossimità del valore 10 :
32 32 32 32 32
10 0,001⋅10 0,002⋅10 0,103⋅10 0,999⋅10
32
0,001⋅10
In questo caso, la spaziatura tra numeri consecutivi è diventata uguale a [Link] visione d'insieme
dei numeri rappresentabili darebbe quindi luogo a un'immagine simile a questa (viene rappresentato
solo il semiasse positivo; sul semiasse negativo la situazione è speculare):
xmax
0
In altre parole, l'insieme finito dei numeri rappresentabili si "addensa" nei pressi dello zero, per poi
assumere un andamento sempre più "sparso" man mano che ci si allontana da zero. Questa è una
caratteristica vantaggiosa della rappresentazione in virgola mobile, in quanto consente di
rappresentare con maggiore "finezza" i valori molto piccoli (dove piccole differenze hanno un valore
relativo molto grande), e con maggiore "grossolanità" i valori via via più grandi, dove piccole
differenze diventano meno rilevanti (per esempio,una differenza pari a 10-100 tra due numeri vicini a
zero può essere significativa, mentre la stessa differenza è del tutto trascurabile tra due numeri vicini
a 1030).
A questo punto possiamo chiederci come rappresentare i valori reali che non sono compresi
nell'insieme dei valori rappresentabili esattamente. Sia x un numero reale non rappresentabile
esattamente. Dobbiamo distinguere tre casi:
• | x | > xmax: in questo caso x è fuori dell'intervallo di rappresentazione, e non è
rappresentabile;
• | x | < xmin: anche in questo caso x è fuori dell'intervallo di rappresentazione, tuttavia in
questo caso una soluzione ragionevole potrebbe essere quella di approssimare x con zero;
25
•xmin ≤ | x | ≤ xmax: in questo caso x viene approssimato con il più vicino numero esattamente
rappresentabile.
Esempio
Consideriamo B = 10, h = 2, e k = 3, e un numero x = 28,976 = 0,28976·102. E' evidente che x
è compreso nell'intervallo di rappresentazione, ma non è rappresentabile esattamente. I due numeri x'
e x" più vicini a x e rappresentabili esattamente sono:
x' = 0,289·102, x" = 0,290·102, con x' < x <x"
le cui rappresentazioni in forma grafica sono date da:
x':
+ 2 8 9 + 0 2
x":
+ 2 9 0 + 0 2
Il valore più vicino a x risulta essere x", che viene quindi scelto come rappresentazione
(approssimata) di x.
Fine esempio
zero;
e e
2.3: mmin B min < | x op y | < mmax·B max : rimedio: approssimare il risultato con il valore
Esempio
Consideriamo una rappresentazione in virgola mobile con B = 10, h = 2, e k = 3:
1. risultato rappresentabile esattamente:
+ 2 3 0 + 0 8 + + 1 1 8 + 0 8 = + 3 4 8 + 0 8
2.1. overflow:
+ 1 8 3 + 3 3 x + 2 0 0 + 7 8 = ? ? ? ? ? ? ?
26
(il risultato esatto sarebbe: 0,366·10110)
2.2. underflow:
+ 0 0 1 - 9 9 : + 2 0 0 + 0 1 = ? ? ? ? ? ? ?
-100
(il risultato esatto sarebbe: 0,005·10 )
2.3. approssimazione:
+ 7 4 8 + 0 4 + + 6 1 9 + 0 4 = + 1 3 7 + 0 5
(il risultato esatto sarebbe: 1,367·104 = 0,1367·105)
Fine esempio
Esempio
Consideriamo una rappresentazione in virgola mobile con B = 10, h = 2, e k = 3. Dati x1 =
0,235·103 , e x2 = 0,822·105, l'algoritmo per il prodotto viene applicato nel modo seguente:
1. m <-- 0,19317 // (= 0,235·0,822)
2. e <-- 8 // (= 3+5)
27
3. se (numero cifre in 0,19317 è > 3) allora: m <-- 0,193
4. restituisci ,come risultato la coppia (0,193, 8)
Quindi il risultato dell'operazione 0,235·103 · 0,822·105 viene calcolato come pari a 0,193·108;
si noti la differenza rispetto al risultato esatto.
Fine esempio
Somma
Per calcolare la somma x1 + x2 occorre che le mantisse siano "allineate", cioè che e1 = e2. Se
questo non è vero, allora occorre prima uguagliare uno dei due esponenti all'altro, modificando
opportunamente la corrispondente mantissa, e poi procedere a calcolare la somma. I passi da seguire
sono quindi:
1. se e1 ≠ e2, allora: m2 <-- m2·B(e2-e1)
e2 <-- e1 //"allineamento" delle mantisse
2. m <-- m1 + m2
3. e <-- e1
4. se (parte intera di m è >0), allora: "sposta" virgola, e "riaggiusta" esponente e
5. se (numero cifre mantissa è > k) allora: approssima mantissa
6. restituisci come risultato la coppia (m, e)
Esempio
Consideriamo una rappresentazione in virgola mobile con B = 10, h = 2, e k = 3. Dati x1 =
0,932·104 , e x2 = 0,999·103, l'algoritmo per la somma viene applicato nel modo seguente:
1. se 4 ≠ 3, allora: m2 <-- 0,0999 // (= 0,999·10(3-4) )
e2 <-- 4
2. m <-- 1,0319 // (= 0,932 + 0,0999 )
3. e <-- 4
4. se (parte intera di 1,0319 è >0), allora: m <-- 0,10319, e <-- 5
5. se (numero cifre 0,10319 è > 3) allora: m <-- 0,103
6. restituisci come risultato la coppia (0,103, 5)
Quindi il risultato dell'operazione 0,932·104 + 0,999·103 viene calcolato come pari a 0,103·105;
si noti la differenza rispetto al risultato esatto.
Fine esempio
Dalla descrizione fatta, appare evidente come gli algoritmi per l'esecuzione delle operazioni
aritmetiche tra numeri rappresentati in virgola mobile sono più complessi (nel senso che richiedono
più tempo per essere eseguiti) rispetto ai corrispondenti algoritmi da applicare a numeri interi con
rappresentazione posizionale. Inoltre, si tratta di una aritmetica inerentemente approssimata, per le
ragioni spiegate in precedenza. Questo è il motivo per cui, a meno che non sia strettamente
indispensabile, conviene utilizzare il tipo di dato “intero” per rappresentare informazione di tipo
numerico, piuttosto che il tipo “reale”.
28
ESERCIZI DI VERIFICA
1) Date le seguenti rappresentazioni posizionali in base B di numeri interi, quale è il valore numerico
corrispondente (espresso nella usuale notazione decimale)?
base B = 2: 10001 0110 10110
base B= 5: 302 10001 104
base B=7: 104 6002 325
3) Date le seguenti coppie di valori che rappresentano mantissa ed esponente di numeri espressi in
virgola mobile, calcolare il corrispondente valore numerico espresso in notazione decimale (nota:
mantissa ed esponente si intendono rappresentati in modulo e segno):
base B=2: (+0.1101 +10) (+0.0110 - 01)
base B=8: (- 0.0110 - 01) (- 0.706 +03)
4) Quale è il più grande numero positivo rappresentabile in una notazione in virgola mobile con base
B=5, h=2 cifre per l'esponente, e k=3 cifre per la mantissa? Scrivere la rappresentazione in virgola
mobile in base 5 di tale numero (coppia mantissa ed esponente) e calcolare il suo valore numerico
espresso in notazione decimale (nota: mantissa ed esponente si intendono rappresentati in modulo e
segno; lo spazio occupato dai due segni non è incluso in k e h).
5) Quale è il più piccolo numero positivo rappresentabile in una notazione in virgola mobile con base
B=5, h=2 cifre per l'esponente, e k=3 cifre per la mantissa? Scrivere la rappresentazione in virgola
mobile in base 5 di tale numero (coppia mantissa ed esponente) e calcolare il suo valore numerico
espresso in notazione decimale (nota: mantissa ed esponente si intendono rappresentati in modulo e
segno; lo spazio occupato dai due segni non è incluso in k e h).
6) Eseguire le seguenti operazioni tra numeri rappresentati in virgola mobile (coppia mantissa-
esponente), con base B=10 e k=3 cifre per la mantissa e h=2 cifre per l'esponente, rispettivamente. Il
risultato deve essere espresso nella stessa rappresentazione, rispettando i vincoli su k e h; quindi,
dove opportuno, si dovrà procedere ad eventuali arrotondamenti (nota: mantissa ed esponente si
intendono rappresentati in modulo e segno; lo spazio occupato dai due segni non è incluso in k e h):
(+0.302 - 31) * (+0.236 +25) (+0.700 + 80) * (+0.296 +35)
29
(+0.302 - 01) + (+0.736 +02) (- 0.088 - 31) / (+0. 100 +25)
(- 0.080 +11) - (+0. 101 +12) (- 0.777 - 31) / (+0. 613 +78)
In quali casi si verifica un errore?
7) Scrivere un programma che riceve in ingresso un numero intero b≥2 e un numero reale f, 0<f<1
(scritto nella notazione decimale), e stampa la rappresentazione in base b di f. (Nota: nella
conversione da base 10 a base b, la rappresentazione risultante potrebbe essere costituita da un
numero infinito di cifre; scrivere il programma in modo che l'operazione di conversione si arresti al più
dopo aver generato un numero prefissato di cifre).
8) Scrivere un programma che riceve in ingresso 2 coppie di valori (m1 e1), (m2 e2) (dove ogni
coppia è formata da un numero reale e da un numero intero). Considerando gli elementi di ogni
coppia come mantissa ed esponente di una rappresentazione (in base 10) in virgola mobile di numeri
reali, il programma deve applicare l'operazione di somma ai due numeri rappresentati (m1 e1), (m2
e2) e stampare il risultato, sempre sotto forma di una coppia opportuna (m e) (mantissa ed
esponente). Verificare la correttezza del programma eseguendolo con differenti dati in ingresso.
10) Estendere il programma scritto per l'esercizio 9, in modo tale che, ad ogni iterazione, il
programma riceva in ingresso 2 nuove coppie di valori (m1 e1), (m2 e2), e un carattere c
appartenente all'insieme {+, -, *, /}, e applichi l'operazione rappresentata da c ai due numeri
rappresentati da (m1 e1), (m2 e2). Verificare la correttezza del programma eseguendolo con
differenti dati in ingresso (nota: prima di scrivere il programma, progettare gli opportuni algoritmi!).
30