Tipi Interi e Tipi Floating Point in Java

Concetti Chiave
  • Java definisce quattro tipi di interi: byte, short, int e long, tutti con segno (signed).
  • La dimensione di ciascun tipo determina il suo intervallo di valori, non necessariamente la memoria occupata.
  • Esempi: byte (8 bit), short (16 bit), int (32 bit) e long (64 bit).
  • Java non supporta interi senza segno; i tipi sono sempre con segno (signed).
  • I tipi in virgola mobile (float e double) seguono lo standard IEEE-754 e offrono precisione singola e doppia rispettivamente.
  • float utilizza 32 bit, mentre double utilizza 64 bit, rendendolo più adatto per calcoli ad alta precisione.
  • La scelta del tipo dipende dalle esigenze relative a intervallo, precisione e ottimizzazione delle performance.

Interi

Java definisce quattro tipi di intero: byte, short, int e long. Tutti questi tipi sono con segno, quindi possono rappresentare valori positivi e negativi.

Java non supporta interi senza segno, cioè solo positivi. Molti altri linguaggi di programmazione supportano sia interi con segno sia interi senza segno. Tuttavia, i progettisti di Java hanno ritenuto non necessari gli interi senza segno.

In particolare, hanno considerato che il concetto di unsigned venisse usato principalmente per specificare il comportamento del bit più significativo, che definisce il segno di un valore intero. Come vedremo nelle prossime lezioni, Java gestisce il significato del bit più significativo in modo diverso, introducendo un operatore speciale di “shift a destra senza segno”. Di conseguenza, la necessità di un tipo intero unsigned è stata eliminata.

La larghezza di un tipo intero non va intesa come la quantità di memoria che occupa, bensì come il comportamento che definisce per le variabili e le espressioni di quel tipo.

L’ambiente di esecuzione di Java è libero di usare la dimensione che preferisce, purché i tipi si comportino come dichiarato. Le larghezze e gli intervalli di questi tipi interi variano ampiamente, come mostrato nella tabella seguente:

Nome Larghezza Intervallo
long 64 −9 223 372 036 854 775 808 a 9 223 372 036 854 775 807
int 32 −2 147 483 648 a 2 147 483 647
short 16 −32 768 a 32 767
byte 8 −128 a 127
Tabella 1: Tipi interi in Java

Si esaminerà ora ciascun tipo di intero.

Tipo byte

Il più piccolo tipo intero è byte. Si tratta di un tipo con segno a 8 bit con un intervallo che va da −128 a 127.

Le variabili di tipo byte risultano particolarmente utili quando si lavora con flussi di dati provenienti da una rete o da un file. Sono utili anche quando si gestiscono dati binari grezzi che potrebbero non essere direttamente compatibili con gli altri tipi integrati di Java.

La dichiarazione di variabili byte avviene mediante la parola chiave byte. Ad esempio, il codice seguente dichiara due variabili byte chiamate b e c:

byte b, c;

Tipo short

short è un tipo con segno a 16 bit. Ha un intervallo che va da −32 768 a 32 767. Probabilmente è il tipo meno utilizzato in Java. Ecco alcuni esempi di dichiarazione di variabili short:

short s;
short t;

Tipo int

Il tipo intero più comunemente usato è int. Si tratta di un tipo con segno a 32 bit con un intervallo che va da −2 147 483 648 a 2 147 483 647. Oltre ad altri impieghi, le variabili di tipo int sono spesso utilizzate per controllare i cicli e per indicizzare gli array.

Sebbene si possa pensare che usare un byte o uno short sia più efficiente di un int quando non è necessario un intervallo così ampio, ciò potrebbe non essere vero. Infatti, quando valori byte e short sono usati in un’espressione, vengono promossi a int durante la valutazione (la promozione di tipo è descritta più avanti in questo capitolo). Pertanto, int è spesso la scelta migliore quando serve un intero.

Tipo long

long è un tipo con segno a 64 bit ed è utile quando un int non è sufficientemente grande per contenere il valore desiderato. L’intervallo di un long è molto ampio, il che lo rende adatto quando servono numeri interi grandi. Ecco un programma che calcola il numero di miglia percorse dalla luce in un numero specificato di giorni:

// Calcola la distanza percorsa dalla luce usando variabili long.
class Luce {
    public static void main(String[] args) {
        int velocitaLuce;
        long giorni;
        long secondi;
        long distanza;

        // velocità approssimativa della luce in miglia al secondo
        velocitaLuce = 186000;

        giorni = 1000; // specificare qui il numero di giorni

        secondi = giorni * 24 * 60 * 60; // converte in secondi

        distanza = velocitaLuce * secondi; // calcola la distanza

        System.out.print("In " + giorni + " giorni la luce percorrerà circa ");
        System.out.println(distanza + " miglia.");
    }
}

Questo programma genera il seguente output:

In 1000 giorni la luce percorrerà circa 1607040000000 miglia.

È evidente che il risultato non avrebbe potuto essere contenuto in una variabile di tipo int.

Tipi in virgola mobile

I numeri in virgola mobile, noti anche come numeri reali, vengono utilizzati quando si valutano espressioni che richiedono precisione frazionaria.

Ad esempio, calcoli come la radice quadrata, o funzioni trascendenti quali seno e coseno, producono un valore la cui precisione richiede un tipo in virgola mobile. Java implementa l’insieme standard (IEEE-754) di tipi e operatori in virgola mobile. Esistono due tipi in virgola mobile, float e double, che rappresentano rispettivamente numeri a precisione singola e a precisione doppia. Le loro larghezze e i relativi intervalli sono mostrati qui:

Nome Larghezza in bit Intervallo approssimativo
double 64 4.9e−324 a 1.8e+308
float 32 1.4e−045 a 3.4e+038
Tabella 2: Tipi in virgola mobile in Java

Ciascuno di questi tipi in virgola mobile è esaminato di seguito.

Tipo float

Il tipo float specifica un valore a precisione singola che utilizza 32 bit di memoria. La precisione singola è più veloce su alcuni processori e occupa metà dello spazio di una precisione doppia, ma diventa imprecisa quando i valori sono molto grandi o molto piccoli.

Le variabili di tipo float sono utili quando occorre una componente frazionaria, ma non è necessario un elevato grado di precisione. Ad esempio, float può risultare utile quando si rappresentano dollari e centesimi.

Di seguito alcuni esempi di dichiarazioni di variabili float:

float tempAlta, tempBassa;

Tipo double

La precisione doppia, indicata dalla parola chiave double, utilizza 64 bit per memorizzare un valore. Su alcuni moderni processori ottimizzati per calcoli matematici ad alta velocità, la precisione doppia è in realtà più veloce della precisione singola.

Tutte le funzioni matematiche trascendenti, come sin(), cos() e sqrt(), restituiscono valori double. Quando è necessario mantenere l’accuratezza su molte iterazioni di calcolo o si stanno manipolando numeri di grande valore, double è la scelta migliore.

Segue un breve programma che utilizza variabili double per calcolare l’area di un cerchio:

// Calcola l'area di un cerchio.
class AreaCerchio {
    public static void main(String[] args) {
        double piGreco, raggio, area;

        raggio = 10.8; // raggio del cerchio
        piGreco = 3.1416; // pi greco, approssimativamente
        area = piGreco * raggio * raggio; // calcola l'area

        System.out.println("L'area del cerchio è " + area);
    }
}