Tipi in Virgola Mobile in Linguaggio C

Dopo i tipi numerici interi, vediamo ora come il linguaggio C gestisce i numeri reali.

In particolare, vedremo come il linguaggio C rappresenta i numeri reali e quali tipi mette a disposizione per manipolarli: float, double e long double.

Tipi in Virgola Mobile

I tipi interi non sono adatti a tutte le applicazioni. Spesso, sorge l'esigenza di utilizzare variabili in grado di rappresentare e manipolare valori che hanno una parte frazionaria e, in generale, numeri reali.

In particolare, potrebbe sorgere l'esigenza di rappresentare numeri reali molto piccoli o molto grandi, come ad esempio le distanze tra le stelle o le dimensioni atomiche.

Per questo motivo, il linguaggio C, come la stragrande maggioranza dei linguaggi, permette di rappresentare tali valori utilizzando il formato in virgola mobile.

Questo tipo di rappresentazione prende il nome dal fatto che la virgola decimale può muoversi all'interno del numero, permettendo di rappresentare valori molto grandi o molto piccoli.

Lo studio approfondito del funzionamento dei numeri in virgola mobile è un argomento complesso e prende il nome di analisi numerica. Rimandiamo al corso di Analisi Numerica per un approfondimento su questo argomento.

In questa sede ci limitiamo a fornire una panoramica generale sul funzionamento dei numeri in virgola mobile in linguaggio C.

Il linguaggio C fornisce tre tipi in virgola mobile:

  • float: rappresenta un numero in virgola mobile a precisione singola;
  • double: rappresenta un numero in virgola mobile a precisione doppia;
  • long double: rappresenta un numero in virgola mobile a precisione estesa.

Tipicamente, il tipo float è adatto ai casi in cui la precisione di cui si ha bisogno non è critica. Ad esempio quando una o due cifre decimali sono più che sufficienti nei calcoli.

Il tipo double, invece, è quello più adoperato in quanto offre una maggiore precisione rispetto al tipo float. In generale, il tipo double è quello che viene utilizzato di default quando si hanno a che fare con numeri in virgola mobile. Ha lo svantaggio, però, che i calcoli possono essere più lenti rispetto al tipo float.

Infine, il tipo long double è quello che offre la maggiore precisione ma viene raramente adoperato per i motivi che vedremo tra poco.

Lo standard del C non specifica la precisione di ciascun tipo in virgola mobile. Questo perché processori diversi potrebbero memorizzare i numeri in virgola mobile in maniera diversa.

Oggigiorno, però, la maggior parte dei processori segue lo standard IEEE 754 che fu introdotto per ovviare a questo problema. Ormai è diventato rarissimo trovare processori che non seguano tale standard. I processori con architettura x86 o ARM, ad esempio, seguono tutti tale standard.

Standard IEEE 754

Lo standard IEEE 754 fu sviluppato dalla IEEE (Institute of Electrical and Electronics Engineers) per definire un formato standard per la rappresentazione dei numeri in virgola mobile.

Questo standard definisce due formati primari per la rappresentazione dei numeri: precisione singola che sfrutta 32 bit e precisione doppia che sfrutta 64 bit.

I numeri che rispettano lo standard IEEE 754 sono rappresentati in notazione scientifica normalizzata. Questo significa che il numero è diviso in tre parti:

  • Segno s: un bit che rappresenta il segno del numero. 0 per i numeri positivi, 1 per i numeri negativi.
  • Esponente e: una serie di bit che rappresenta l'esponente del numero.
  • Mantissa M: una serie di bit che rappresenta la parte frazionaria del numero.

Per cui, informalmente, un numero in virgola mobile ha una forma del genere:

s \cdot M \cdot 2^{e}

Il numero di bit riservati per l'esponente determinano quanto grande o piccolo il numero possa essere, mentre i bit della mantissa ne determinano, approssimativamente, la precisione.

Nel caso dei numeri a precisione singola, float, per l'esponente vengono usati 8 bit mentre per la mantissa vengono usati 23 bit. Il bit rimanente viene utilizzato per il segno.

Motivo per cui, un numero a precisione singola può assumente un valore massimo di circa:

2^{128} \approx 3.4 \times 10^{38}

ed ha una precisione di circa 6 cifre decimali.

Lo standard descrive, inoltre, altri due formati: precisione estesa singola e precisione estesa doppia. Tuttavia, non ne specifica la dimensione in bit e la loro implementazione è lasciata alla discrezione del produttore del processore.

Per tal motivo, nella pratica i tipi float e double sono quelli che vengono utilizzati di più in quanto garantiscono una rappresentazione standardizzata e portabile tra i vari processori.

double e float in C

Come detto sopra, quindi, quasi tutti i compilatori C e i processori seguono lo standard IEEE 754 per la virgola mobile. Pertanto, il tipo float equivale a un numero a precisione singola a 32 bit mentre il tipo double equivale a un numero a precisione doppia a 64 bit.

Nella tabella che segue sono riportati i valori minimo, massimo e la precisione caratteristica di questi due tipi:

Tipo Minimo Valore Positivo Massimo Valore Positivo Precisione
float 1.17549 \times 10^{-38} 3.40282 \times 10^{38} 6 cifre decimali
double 2.22507 \times 10^{-308} 1.79769 \times 10^{308} 15 cifre decimali
Tabella 1: Caratteristiche dei tipi in virgola mobile del C

Dalla tabella abbiamo omesso il tipo long double in quanto la sua dimensione può variare da processore a processore.

Ovviamente, la tabella non vale per i processori che non seguono lo standard IEEE 754. In tal caso, i valori potrebbero essere diversi.

Ricapitolando:

Definizione

Tipi in Virgola Mobile in C

Il linguaggio C fornisce tre tipi in virgola mobile:

  • float: rappresenta un numero in virgola mobile a precisione singola;
  • double: rappresenta un numero in virgola mobile a precisione doppia;
  • long double: rappresenta un numero in virgola mobile a precisione estesa.

Se il compilatore (ed il processore) seguono lo standard IEEE 754 allora le dimensioni di float e double sono note e corrispondono a 32 e 64 bit rispettivamente.

Ciò non vale per long double.

In Sintesi

In questa lezione abbiamo studiato che:

  • Per rappresentare numeri reali in C si utilizza il formato in virgola mobile;
  • Il linguaggio C fornisce tre tipi in virgola mobile: float, double e long double;
  • I tipi float e double sono i più utilizzati in quanto seguono lo standard IEEE 754 ormai adottato dalla stragrande maggioranza dei processori;
  • Il tipo float è adatto ai casi in cui la precisione non è critica, mentre il tipo double è quello più utilizzato;
  • Il tipo long double offre la maggiore precisione ma è poco utilizzato in quanto la sua dimensione può variare da processore a processore.

Nella prossima lezione studieremo come scrivere nei nostri programmi costanti letterali in virgola mobile.