Skillbook Logo
foto profilo

Skill Factory

Lista post > Competenze per programmare: la rappresentazione digitale dei numeri interi e decimali

Competenze per programmare: la rappresentazione digitale dei numeri interi e decimali

Gino Visciano | Skill Factory - 24/03/2024 21:11:45 | in Tutorials

I numeri che usiamo si chiamano "Numeri reali", in base alle loro caratteristiche li possiamo organizzare nei seguenti insiemi:

I numeri, sia interi (relativi), sia decimali (razionali), servono per esprimere rispettivamente quantità intere o frazionarie.

Sono irrazionali i numeri che non si possono indicare attraverso il rapporto tra numeri interi, come ad esempio il pi greco, che indica il rapporto tra la misura della circonferenza di un cerchio e il suo diametro oppure il numero di Nepero (e).

In programmazione per indicare la parte decimale di un numero si usa il punto "." al posto della virgola ",", quindi negli esempi userò questa convenzione.

Esempio 1

Per indicare la quantità di auto nell'immagine seguente, basta usare il numero intero 9:

mentre per indicare la quantità di auto nell'immagine seguente, bisogna usare il numero decimale 8.5, perché l'ultima auto è divisa a metà:

 

Esempio 2

Il risultato dell'espressione 10/2 è 5 che è un numero intero, perché il numero 10 può essere diviso esattamente in due parti intere, ciascuna composta da 5 unità.

Il risultato dell'espressione 10/3 è 3.33333 che è un numero decimale, perché il numero 10 può essere diviso in 3 parti intere, ciascuna composta da 3 unità, ma ne resta una che deve essere frazionata in 3 parti decimali da 0.33333.

Attenti, quando la quantità di cifre decimali di un numero è indefinita, ovvero quando l'unità non è divisibile in parti esattamente uguali, come nel caso del riusultato della divisione 10/3 = 3.33333..., il numero può essere scritto nel modo seguente:

e si legge 3.3 periodico, perché il numero di 3 della parte decimale potrebbe essere infinito.

In programmazione, quando il numero di decimali è periodico, bisogna indicare la precisione del numero ovvero il numero di cifre da indicare dopo la virgola, per questo motivo nei linguaggi di programmazione si fa la distinzione tra numeri decimali a singola precisione (float) e doppia precisione (double). Di solito i numeri a doppia precisione si usano in ambiti scientifici, quelli a singola precisione per tutti gli altri ambiti.

Esempio 3 

I numeri si possono anche rappresentare sugli assi cartesiani, come mostra l'immagine seguente:

Se l'asse cartesiano è orizzontale si chiama asse delle ascisse e si indica con la lettera X, mentre se è verticale si chiama asse delle ordinate e si indica con la lettera Y.

Un piano su cui si disegna sia l'asse delle "Ascisse", sia l'asse delle "Ordinate" viene detto "Piano Cartesiano".

Il numero 0, si trova nel punto in cui gli assi X e Y s'incontrano e viene chiamato origine. Lo zero divide i numeri positivi (segno +) da quelli negativi (segno -) di entrambi gli assi; sia i numeri positivi, sia i numeri negativi sono infiniti.

Attenti, quando scrivete un numero positivo, non siete obbligati ad indicare il segno +, mentre quando scrivete un numero negativo il segno - è obbligatorio.

Sugli assi cartesiani, la parte decimale di un numero è sempre compresa nel segmento che unisce due numeri interi consecutivi. 

L'immagine seguente mostra la posizione del numero 2.5 sull'asse X:

Ricordate che il punto centrale di un segmento che lo divide in due parti uguali è detto punto medio.

L'immagine seguente mostra la posizione del il numero -3.2 sull'asse X:

Per indicare la parte decimale 0.2 dovete posizionarvi esattamente nel punto che corrisponde alla quinta parte del segmento, perché 1/5=0.2, come mostra l'immagine.

Come ci ha insegnato il filosofo greco Democrito, un segmento può essere diviso infinite volte, per questo motivo la quantità di cifre decimali di un numero può anche essere molto grande; maggiore è il numero di decimali, tanto maggiore è il numero di volte che vengono divise le parti del segmento. La precisione, ovvero la quantità di cifre decimali di un numero, serve per capire fino a quando dobbiamo continuare  dividere le parti del segmento, per evitare di continuare all'infinito.  

In che modo i computer memorizzano i numeri interi?

I computer sono macchine elettroniche di tipo digitale, a differenza degli uomini, per scrivere i numeri possono usare solo due cifre: 0 e 1 chiamate bit (binary digit), per questo motivo usano il sistema di numerazione binario.  

I computer memorizzano i numeri nella RAM (Random Access Memory); la memoria ad accesso casuale composta da tanti interruttori, chiamati flip-flop, che permettono di scrivere i numeri in forma binaria - se l'interruttore spento (-) la cifra è zero, se è acceso (+) la cifra è uno. 

    

Clicca qui per conoscere la differenza tra mondo reale e mondo digitale.

Nei linguaggi di programmazione le variabili oppure gli oggetti che possono contenere tipi interi si dichiarano con: int oppure Integer, ad esempio:

int x=10;

Integer y=20;

In SQL le colonne di una tabella che possono contenere numeri interi di dichiarano con la parola chiave numeric, ad esempio:

create table magazzino(id numeric(7), quantita numeric(7),...);

Quando un computer memorizza nella RAM un numero intero, usa il primo bit a sinistra (quello più significativo) per indicare il segno; se il primo bit più significativo è 0 il numero intero è positivo, altrimenti è negativo. Gli altri bit servono per indicare il modulo del numero intero.

Per i numeri positivi, il modulo è rappresentato semplicemente dal valore binario del numero da memorizzare.

Per i numeri negativi, il modulo è rappresentato in complemento a 2.

Ad esempio, se il computer usa 32 bit (4 byte) per memorizzare un numero intero con il segno (int signed), con 4 byte si può scrivere qualunque numero intero, negativo o positivo, compreso nell'intervallo: –2.147.483.648 e 2.147.483.647.

2.147.483.647 = [0](segno)[1111111 11111111 11111111 11111111](modulo = valore binario del numero 2147483647)

–2.147.483.648  = [1](segno)[00000000 00000000 00000000 00000000](modulo = complemento a 2 del numero 2147483648)

Complemento a 2

Per calcolare il complemento a 2 di un numero binario è semplice, basta invertire i valori dei bit, gli zeri diventano uno e gli uno diventano zero e aggiungere 1 al numero che si ottiene.

Ad esempio, il complemento a 2 binario del numero 10 (decimale) si calcola nel modo seguente:

1) converto il numero 10 decimale in binario:

10 (decimale) = 1010 (binario)

2) Calcolo il complemento a 1 del numero 1010 invertendo gli zeri con uno e gli uno con zero:

1010 (binario) = 0101 (complemento a 1)

3) aggiungo 1 al numero 0101:

0101+
0001=
---------
 0110 (Complemento a 2 del numero binario 1010)

Allo stesso modo possiamo calcolare il complemento a 2 del numero decimale 2.147.483.648:

1) converto il numero 2.147.483.648 decimale in binario:

2.147.483.648 (decimale) = 10000000 00000000 00000000 00000000  (binario)

2) Calcolo il complemento a 1 del numero 10000000 00000000 00000000 00000000  invertendo gli zeri con uno e gli uno con zero:

10000000 00000000 00000000 00000000  (binario) = 01111111 11111111 11111111 11111111 (complemento a 1)

3) aggiungo 1 al numero 01111111 11111111 11111111 11111111:

01111111111111111111111111111111+
00000000000000000000000000000001=
-----------------------------------------------------------
10000000000000000000000000000000 (Complemento a 2 del numero binario 01111111
111111111111111111111111)

Attenti, nella rappresentazione dei computer a 32 bit, giacché l'ultimo bit serve per il segno, vengono memorizzati solo i primi 31 bit.
 
In che modo i computer memorizzano i numeri decimali?
I numeri decimali possono essere a virgola fissa oppure a virgola mobile. In quelli a virgola fissa le quantità di decimali dopo la virgola è predefinita, quindi la posizione della virgola non cambia, mentre per quelli a virgola mobile la quantità di decimali può variare, quindi la posizione della virgola più cambiare.
 
Nei linguaggi di programmazione i tipi float e double indicano numeri decimali a virgola mobile, la differenza è la precisione, i double hanno un maggior numero di decimali dopo la virgola rispetto ai float. Il tipo decimal usato in SQL per impostare le colonne con numeri decimali è a virgola fissa. La parola chiave decimal permette di specificare sia la quantità di cifre totali che compongono il numero, sia quanti sono quelli decimali, ad esempio:
create table dipendenti (
...
stipendio decimal(9,2),
...)
 

La rappresentazione nei computer a virgola fissa è molto semplice: il byte più significativo rappresenta il segno, un certo numero di byte viene utilizzato per rappresentare la parte intera, segue quindi un altro numero di byte per rappresentare la parte decimale, come mostra l'immagine seguente:

Ad esempio, convertiamo in binario il numero decimale 17,55, immaginando di avere 16 bit a disposizione:

1) Il bit più significativo è uguale a 0, perché il numero è positivo.
2) La parte intera, immaginiamola di 7 bit, è uguale a:

2^6=64 -> 0
2^5=32 -> 0
2^4=16 -> 1
2^3=8 -> 0
2^2=4 -> 0
2^1=2 -> 0
2^0=1 -> 1

17 (decimale) = 0010001 (binario)

Se la parte intera fosse stata negativa avremmo dovuto calcolare il complemento a 2.

3) La parte decimale, immaginandola di 8 bit, è uguale a:

2^-1=0.5 -> 1
2^-2=0.25 -> 0
2^-3=0.125 -> 0
2^-4=0.0625 -> 0
2^-5=0.03125 -> 1
2^-6=0,015625 -> 1
2^-7=0,0078125 -> 0
2^-8=0,00390625 -> 0

0.55 (decimale) = 10001100 (binario)

Quindi

17.55 (decimale) =0(segno) 0010001.10001100

Ricordate che il simbolo ^ indica la potenza.
 
Per la rappresentazione dei numeri decimali in virgola mobile i computer usano lo standard IEEE 754 con il quale si definiscono due formati: uno per la precisione singola a 32 bit e l'altro per la precisione doppia a 64 bit.
 
Questo standard segue la notazione scientifica e permette al computer di memorizzare i numeri decimali attraverso tre tipi d'informazioni:
 
 
I bit per la precisione singola hanno la seguente organizzazione:

bit 31 (1) segno
bit 23-30 (8) esponente
bit 0-22 (23) mantissa

mentre per la precisione doppia l'organizzazione è la seguente:

bit 63 (1) segno
bit 52-62 (11) esponente
bit 0-51 (52) mantissa

Il numero viene composto in base alla formula seguente:
 
Numero = (-1)^segno*2^esponente*mantissa
 
Facciamo un esempio:
 
Rappresentiamo in virgola mobile a precisione singola il numero decimale 13.25:
 
1) Il bit più significativo è uguale a 0 perché il numero è positivo
2) Il modulo della parte intera 13 (decimale) è uguale a: 1101 (binario)
3) la parte decimale 0.25 è uguale a: 01 (binario)
 
Quindi
 
13.25 (decimale) = 1101.01 (binario)
 
Usando la notazione scientifica in base 2 lo riscrivo nella forma:
 
1.10101 * 2^3.
 
A questo punto ho tutte informazioni per ottenere il segno, l'esponente e la mantissa:
 
SEGNO=0
ESPONENTE=3+127=130 (decimale) = 10000010 (binario)
 
Per ottenere la mantissa basta prendere il numero 1.10101 ed escludere l'1 prima della virgola, quindi:
 
MANTISSA= 10101 (binario)
 
Il risultato finale è il seguente:
 

 INFORMATICA APPLICATA

Laboratorio

Creare un programma che trasforma i numeri interi nella rappresentazione binaria a 32 bit usata dai computer per memorizzare le informazioni numeriche.

Soluzione JavaScript


// Funzioni
function convertiBinario(numeroIntero){
    let numeroBinario=[]
    let resto
    while (numeroIntero>1){
        resto=numeroIntero%2
        numeroBinario.push(resto)
        numeroIntero=Math.floor(numeroIntero/2)
    }
    numeroBinario.push(numeroIntero)
    for(let i=31-numeroBinario.length;i>0;i--){
        numeroBinario.push(0)
    }
    numeroBinario.reverse()
    return numeroBinario
}

function complemento2(numeroBinario){
    let inverti=[1,0]
    riporto=1
    for (let i=0;i<numeroBinario.length;i++){
        numeroBinario[i]=inverti[numeroBinario[i]]
    }
    for(let i=numeroBinario.length-1;i>0;i--){
        if (numeroBinario[i]==1 && riporto==1){
            numeroBinario[i]=0
            riporto=1
        }else if (numeroBinario[i]==1 && riporto==0){
            numeroBinario[i]=1
            riporto=0
        }else if (numeroBinario[i]==0 && riporto==1){
            numeroBinario[i]=1
            riporto=0
        }else{
            numeroBinario[i]=0
            riporto=0
        }
    }
}
// Programma
let input=require("readline-sync");
let numeroIntero=0
let numeroBinario=[]
let numeroBinarioStr=""
let segno=0
numeroIntero=parseInt(input.question("Numero intero: "))
while (numeroIntero<-2147483648 || numeroIntero> 2147483647){
    print("Errore: inserire un numero compreso tra -2147483648 e 2147483647")
    numeroIntero=parseInt(input.question("Numero intero: "))
}
if (numeroIntero<0){
    segno=1
    numeroBinario=convertiBinario(-(numeroIntero))
    complemento2(numeroBinario)
}
else if (numeroIntero>0){
    segno=0
    numeroBinario=convertiBinario(numeroIntero)
}
numeroBinarioStr="["+segno+"]["
for (let i=0;i<numeroBinario.length;i++){
    if (i<31){
        numeroBinarioStr+=numeroBinario[i]
    }
}
numeroBinarioStr+="]"
console.log(numeroBinarioStr)

 

Soluzione Python


# Funzioni

# Converte numero intero in binario
def convertiBinario(numeroIntero):
    numeroBinario=[]
    while numeroIntero>1:
        resto=numeroIntero%2
        numeroBinario.append(resto)
        numeroIntero=int(numeroIntero/2)
    numeroBinario.append(numeroIntero)
    for i in range(31-len(numeroBinario)):
        numeroBinario.append(0)
    numeroBinario.reverse()
    return numeroBinario

# Calcola il complemento a due di un numero binario
def complemento2(numeroBinario):
    inverti=[1,0]
    riporto=1
    for i in range(len(numeroBinario)):
        numeroBinario[i]=inverti[numeroBinario[i]]
    for i in range(len(numeroBinario)-1,0,-1):
        if numeroBinario[i]==1 and riporto==1:
            numeroBinario[i]=0
            riporto=1
        elif numeroBinario[i]==1 and riporto==0:
            numeroBinario[i]=1
            riporto=0
        elif numeroBinario[i]==0 and riporto==1:
            numeroBinario[i]=1
            riporto=0
        else:
            numeroBinario[i]=0
            riporto=0

# Programma
numeroIntero=0
numeroBinario=[]
segno=0
numeroIntero=int(input("Numero intero: "))
while numeroIntero<-2147483648 or numeroIntero> 2147483647:
    print("Errore: inserire un numero compreso tra -2147483648 e 2147483647")
    numeroIntero=int(input("Numero intero: "))
if numeroIntero<0:
    segno=1
    numeroBinario=convertiBinario(-(numeroIntero))
    complemento2(numeroBinario)
elif numeroIntero>0:
    segno=0
    numeroBinario=convertiBinario(numeroIntero)
print("["+str(segno)+"][",end="")
for i,x in enumerate(numeroBinario):
    if i<31: print(x,end="")
print("]")


Leggi anche le altre lezioni:

COMPETENZE PER PROGRAMMARE: MONDO REALE E MONDO DIGITALE
COMPETENZE PER PROGRAMMARE: I SISTEMI DI NUMERAZIONE


Segui sul canale YouTube "Skill Factory Channel" la PlayLIst: COMPETENZE PER PROGRAMMARE
Per consultare il catalogo dei corsi online della nostra Academy ...

... collegati al nostro sito: www.skillfactory.it

 

numeri interi numeri decimali virgola fissa virgola mobile complemento a uno complemento a due numeri periodici singola precisione doppia precisione float double integer punto medio decimal numeric mantissa ieee 754 skill factory gino visciano

Share Button
TOP