Tipi Numerici in Virgola Mobile in C#

I tipi interi sono utili per lavorare con numeri interi, ma spesso è necessario lavorare con numeri reali, ossia numeri con una parte intera e una parte decimale.

In C# esistono tre tipi di numeri in virgola mobile:

  • float: 32 bit, precisione singola;
  • double: 64 bit, precisione doppia;
  • decimal: 128 bit, precisione superiore.

In questa lezione vedremo come dichiarare variabili di tipo float, double e decimal, come assegnare valori letterali e come specificare valori in notazione scientifica.

Tipi Floating-Point

Nella lezione precedente abbiamo studiato i tipi numerici interi che il linguaggio C# mette a disposizione. Ne sono presenti ben 8 e si differenziano per il fatto che possono rappresentare o meno numeri negativi, e per la quantità di bit che occupano in memoria e quindi per la grandezza dei numeri che possono rappresentare.

La limitazione di questi tipi risiede nel fatto che essi possono rappresentare esclusivamente numeri interi, senza la virgola.

Quando, invece, si vogliono rappresentare numeri reali, ossia numeri con una parte decimale, come il risultato di una frazione o un numero trascendentale come \pi o e, si utilizzano i tipi floating-point, chiamati in italiano numeri in virgola mobile.

Il funzionamento e la rappresentazione di questi tipi è abbastanza complessa ed è al di fuori dello scopo di questa lezione. Tuttavia, è importante sapere che questi tipi rappresentano i numeri con una parte intera e una parte decimale, e che la loro precisione è limitata.

Nel dettaglio, il loro nome, tradotto in italiano, significa virgola mobile, e ciò è dovuto al fatto che il punto decimale o virgola può muoversi all'interno del numero, in modo da rappresentare numeri molto grandi o molto piccoli. In pratica, il numero di cifre decimali e il numero di cifre intere può variare. Questo per differenziarli dai numeri fixed-point dove il numero di cifre decimali è fisso. Questi ultimi vengono usati in ambiti applicativi molto particolari e in questa guida li tralasceremo.

Il vantaggio di utilizzare i numeri in virgola mobile è che, ad esempio, i due numeri seguenti possono essere rappresentati con uguale precisione:

  • 123456.789
  • 0.000123456789

In particolare, quando si parla di precisione dei numeri in virgola mobile, si parla del numero di cifre significative che è possibile rappresentare. Questo numero dipende dal numero di bit impiegati.

In C# esistono tre tipi di numeri in virgola mobile:

  • float: 32 bit, precisione singola;
  • double: 64 bit, precisione doppia;
  • decimal: 128 bit, precisione superiore.

La differenza tra i tre tipi non risiede semplicemente nel numero di bit utilizzati, che quindi influisce sulla precisione. Infatti i tipi float e double sono direttamente supportati dall'hardware. Essi sono implementati secondo lo standard IEEE 754, che è uno standard internazionale per la rappresentazione dei numeri in virgola mobile. Oggigiorno, la maggior parte dei processori supporta direttamente i numeri in virgola mobile a 32 e 64 bit.

Questa cosa non è vera per il tipo decimal che, invece, è implementato direttamente in software e quindi presenta un overhead in termini di prestazioni. Esso va adoperato quando il livello di precisione richiesto è molto elevato a discapito della velocità di esecuzione.

Anche i numeri in virgola mobile, come gli interi, hanno un intervallo di valori che possono rappresentare. Tuttavia, a differenza degli interi, essi utilizzano la notazione scientifica per rappresentare i numeri. Ad esempio, il numero 123456.789 può essere rappresentato come 1.23456789 \times 10^5.

Nel caso del tipo float, ad esempio, l'intervallo di numeri rappresentabili è compreso tra 3.4 \times 10^{-45} e 3.4 \times 10^{38}, sia negativi che positivi. La precisione è di circa 7 cifre decimali. Ciò significa che il numero 123456.789 può essere rappresentato con precisione, mentre il numero 0.000123456789 no.

Di seguito è riportata una tabella con i tre tipi, il numero di bit impiegati, l'intervallo di numeri rappresentabili e la precisione.

Tipo Bit Intervallo Precisione Supporto hardware
float 32 3.4 \times 10^{-45} \leq x \leq 3.4 \times 10^{38} 7 cifre
double 64 1.7 \times 10^{-308} \leq x \leq 1.7 \times 10^{308} 15 cifre
decimal 128 1.0 \times 10^{-28} \leq x \leq 7.9 \times 10^{28} 28 cifre No
Tabella 1: Tipi in virgola mobile forniti dal C#
Nota

Tipo decimal

Alcune osservazioni sono d'obbligo sul tipo decimal messo a disposizione dal linguaggio C#.

Per prima cosa, bisogna notare che l'intervallo dei numeri rappresentabili è molto più limitato rispetto ai tipi float e double.

Infatti l'intervallo va da 1.0 \times 10^{-28} a 7.9 \times 10^{28}, mentre per i tipi float e double l'intervallo è molto più ampio.

Questo è dovuto al fatto che il tipo decimal è stato progettato per rappresentare numeri con una precisione molto elevata, a discapito dell'intervallo di valori rappresentabili.

Ciò lo rende particolarmente adatto per applicazioni finanziarie oppure per quelle applicazioni in cui è richiesta una precisione molto elevata sui calcoli.

Inoltre, il tipo decimal non è supportato direttamente dall'hardware. Questo significa che l'implementazione di questo tipo è in software e quindi presenta un overhead in termini di prestazioni rispetto ai tipi float e double.

In altre parole, il processore non ha istruzioni specifiche per manipolare i numeri in virgola mobile a 128 bit, quindi il calcolo viene effettuato in software. I tipi float e double, invece, sono supportati direttamente dall'hardware per cui i calcoli sono molto più veloci.

Per dichiarare una variabile di tipo float, double o decimal si procede come segue:

float numeroFloat = 123.456;
double numeroDouble = 123.456;
decimal numeroDecimal = 123.456;

Quindi, così come per tutti i tipi di variabili, si specifica il tipo, il nome della variabile e, opzionalmente, il valore iniziale.

Definizione

Tipi in virgola mobile in C#

Il linguaggio C# mette a disposizione tre tipi di numeri in virgola mobile:

  • float: 32 bit, precisione singola;
  • double: 64 bit, precisione doppia;
  • decimal: 128 bit, precisione superiore.

I tipi float e double sono supportati direttamente dall'hardware, mentre il tipo decimal è implementato in software e presenta un overhead in termini di prestazioni.

Valori letterali dei tipi in virgola mobile

Così come per i valori interi, possiamo inserire all'interno del nostro codice dei valori letterali per i tipi in virgola mobile.

Per farlo è necessario inserire un numero composto da parte intera e parte decimale separati da un punto:

double numeroDouble = 123.456;

In questo caso, numeroDouble è una variabile di tipo double che contiene il valore 123.456.

Un valore letterale floating point può anche essere negativo, basta specificare il segno - (meno) davanti al valore:

double numeroDouble = -123.456;

Normalmente, tutti i valori letterali con la virgola vengono interpretati dal C# come valori di tipo double.

Nel caso in cui si voglia specificare un valore di tipo float, è necessario aggiungere la lettera f alla fine del valore:

float numeroFloat = 123.456f;

Analogamente, per specificare un valore di tipo decimal, è necessario aggiungere la lettera m alla fine del valore:

decimal numeroDecimal = 123.456m;

In questo modo, il compilatore sa che il valore 123.456 deve essere interpretato come un valore di tipo float o decimal.

Da notare che f sta per float, mentre m sta per monetary (monetario) proprio ad indicare il fatto che il tipo decimal è particolarmente adatto per rappresentare valori finanziari dove, spesso, è richiesta una precisione molto elevata.

Definizione

Valori letterali dei tipi in virgola mobile

Un valore letterale con virgola viene interpretato dal C# come un valore di tipo double.

Per specificare un valore di tipo float, è necessario aggiungere la lettera f alla fine del valore, mentre per specificare un valore di tipo decimal, è necessario aggiungere la lettera m.

double numeroDouble = 123.456;
float numeroFloat = 123.456f;
decimal numeroDecimal = 123.456m;

Notazione scientifica

Il linguaggio C# permette anche di specificare i valori in notazione scientifica. Questa notazione è molto utile per rappresentare numeri molto grandi o molto piccoli.

Normalmente, in matematica, fisica o ingegneria, si utilizza la notazione scientifica per rappresentare numeri molto grandi o molto piccoli. Ad esempio, il numero 123456.789 può essere rappresentato come 1.23456789 \times 10^5. In altre parole, si sposta il punto decimale di 5 posizioni verso sinistra mantenendo una sola cifra prima della virgola e si modifica l'esponente del 10:

\begin{array}{c} 123456.789 \\ \downarrow \\ 123456.789 \times 10^0 \\ \downarrow \\ 1.23456789 \times 10^5 \end{array}

Nel caso del linguaggio C# si inserisce soltanto l'esponente da assegnare al 10 preceduto dal carattere e o E:

double numeroDouble  = 1.23456789e5;
double numeroDouble2 = 1.23456789E5;

La lettera e o E sta proprio per exponent (esponente).

In questo caso, numeroDouble e numeroDouble2 contengono lo stesso valore, ossia 1.23456789 \times 10^5. Il carattere e o E indica l'esponente da assegnare al 10.

L'esponente può anche essere negativo. In tal caso basta apporre il segno - (meno) davanti all'esponente:

double numeroDouble = 9.86e-3;

La notazione scientifica ed i suffissi usati per specificare la precisione, f e m, possono essere combinati. Per cui possiamo scrivere un valore in notazione scientifica con la precisione specificata:

float numeroFloat = 1.23456789e5f;
decimal numeroDecimal = 1.23456789e5m;
Definizione

Notazione scientifica in C#

Il linguaggio C# permette di specificare i valori in notazione scientifica.

La sintassi da utilizzare è la seguente:

<parte intera>.<parte decimale>e<esponente>

Dove e è il carattere che indica l'esponente da assegnare al 10.

double esempio = 9.86e-3;

In questo caso, esempio contiene il valore 9.86 \times 10^{-3}.

In Sintesi

In questa lezione abbiamo introdotto i tipi numerici in virgola mobile messi a disposizione dal linguaggio C#.

Abbiamo visto che questi tipi sono utilizzati per rappresentare numeri reali, ossia numeri con una parte intera e una parte decimale.

In particolare, abbiamo visto che:

  • I tipi float e double sono supportati direttamente dall'hardware e sono implementati secondo lo standard IEEE 754.
  • Il tipo decimal è implementato in software e presenta un overhead in termini di prestazioni.
  • I valori letterali con la virgola vengono interpretati come valori di tipo double.
  • Per specificare un valore di tipo float, è necessario aggiungere la lettera f alla fine del valore.
  • Per specificare un valore di tipo decimal, è necessario aggiungere la lettera m alla fine del valore.
  • È possibile specificare i valori in notazione scientifica.

Inoltre, abbiamo visto che il tipo decimal è particolarmente adatto per rappresentare valori finanziari o in generale valori in cui è richiesta una precisione molto elevata.

Nella prossima lezione studieremo i tipi di dato char e string che vengono adoperati per lavorare con il testo.