CodeGym /Corsi /JAVA 25 SELF /Introduzione ai numeri a virgola mobile e al tipo double

Introduzione ai numeri a virgola mobile e al tipo double

JAVA 25 SELF
Livello 6, Lezione 2
Disponibile

1. Numeri a virgola mobile

Supponiamo che tu decida di scrivere una calcolatrice semplicissima. O qualsiasi altro programma in cui servono calcoli (dal banale conteggio del denaro alla fisica complessa). Non tutto nella vita reale è un numero intero — e non ci si può fare nulla!

Quindi armiamoci di un nuovo tipo di dati!

In programmazione i numeri decimali vengono anche chiamati reali o numeri a virgola mobile (floating-point). In Java, come nella maggior parte dei linguaggi, servono per memorizzare non solo interi, ma anche valori «decimali»: vari 3.14, -28.57, 2.718281828...

I numeri a virgola mobile sono di due tipi principali:

Tipo Contiene Intervallo di valori (circa) Precisione Dimensione tipica
float
Numeri ±1.5 × 10-45 ... ±3.4 × 1038 ~7 cifre significative 4 byte
double
Numeri ±5.0 × 10-324 ... ±1.7 × 10308 ~15–16 cifre significative 8 byte

Tipo float

Il tipo float prende il nome da floating-point number — numero a virgola mobile. I numeri reali sono numeri della matematica, hanno proprietà ben definite. Ma il computer ha molte limitazioni. Perciò non è del tutto corretto chiamare i numeri decimali in Java «reali». Per essi si usa il nome «numeri a virgola mobile».

Il tipo float di solito memorizza 7 cifre significative (ad esempio, 0.1234567), l’esponente della base 10 e occupa 4 byte di memoria. È molto poco per calcoli precisi, quindi si è passati rapidamente ai numeri a doppia precisione.

Tipo double

Il tipo double prende il nome da doppia (double) precisione. Occupa 8 byte di memoria (2 volte più di float) e può memorizzare fino a 15 cifre significative: 0.123456789012345. È più che sufficiente per la maggior parte dei calcoli con numeri decimali, perciò double è il tipo principale per memorizzare numeri a virgola mobile in Java.

In questa lezione l’accento principale sarà sul tipo double: è consigliato di default per tutti i numeri «normali» a virgola mobile. Ma più avanti vedremo anche il tipo float.

2. Dichiarazione e inizializzazione delle variabili di tipo double

Tutto come con int — solo che ora usiamo double.

// Dichiariamo una variabile e le assegniamo il valore di pi greco
double pi = 3.1415926;

// Si può dichiarare anche senza inizializzarla
double averageSalary;
averageSalary = 91234.56;

// Si può calcolare!
double pizzaPieces = 8;
double friends = 3;
double piecesPerFriend = pizzaPieces / friends; // 2.666... (e non 2)

Particolarità della sintassi:

  • Come separatore decimale si usa il punto (3.14). Se usi la virgola — otterrai un errore di compilazione!
  • A rigore, scrivendo double d = 3; non otterrai un errore — i tipi vengono convertiti automaticamente (il numero intero si trasforma in «virgola mobile» senza perdite).

3. Input e output di numeri a virgola mobile con Scanner

Per prima cosa proviamo a stampare un numero con la virgola:

double amount = 42.75;
System.out.println(amount); // Stamperà: 42.75

Tutto bene! E se aggiungiamo del testo:

System.out.println("Sul tuo conto: " + amount + " euro."); // Sul tuo conto: 42.75 euro.

Input da tastiera

Per leggere un double bisogna usare un metodo specifico della classe Scanner: console.nextDouble().

Scanner console = new Scanner(System.in);

System.out.println("Inserisci la temperatura esterna:");
double temperature = console.nextDouble(); // Inseriamo direttamente un double

System.out.println("All'esterno adesso: " + temperature + " gradi.");

4. Il tipo double in azione: aritmetica

Tutte le operazioni consuete (+, -, *, /) funzionano come per int:

double distance = 100.5;
double time = 2.0;
double speed = distance / time; // 50.25

System.out.println("Velocità media: " + speed); // Velocità media: 50.25

E questo è tutto per l’aritmetica. Unica differenza: il risultato della divisione è sempre un numero decimale, se almeno uno degli operandi è double.

Confrontiamo con int

int a = 5, b = 2;
System.out.println(a / b); // 2 (il resto viene scartato)

double aa = 5, bb = 2;
System.out.println(aa / bb); // 2.5

5. Errori tipici e stranezze con double

Errore di conversione dell'input

Situazione classica: l’utente inserisce 3,14 — ma il programma si aspetta 3.14. In Java il metodo Scanner.nextDouble() dipende dalla locale corrente: nella locale russa/tedesca la virgola è ammessa, in quella inglese è richiesto il punto. Se necessario, imposta la locale per Scanner oppure leggi una stringa ed esegui il parsing manualmente.

// Questo causerà un problema in Locale.US se viene inserito "3,14"
double value = console.nextDouble();

Errore di «imprecisione» dei numeri nel computer

Qui di solito i principianti iniziano a stupirsi un po’:

double x = 0.1 + 0.2;
System.out.println(x); // Hmm... 0.30000000000000004

Congratulazioni, vi siete imbattuti nella «magia» della rappresentazione dei numeri decimali all’interno del computer. Il punto è che molti numeri non possono essere rappresentati con esattezza in base binaria. Di solito ciò non è critico per la maggior parte delle applicazioni, ma ci sono sfumature in finanza e nelle scienze esatte.

6. Importante: double e int — conversione automatica ed esplicita

Può capitare di sommare un intero e un decimale, o di assegnare un int a una variabile double — non ci saranno errori:

int i = 2;
double d = i; // Tutto ok!
System.out.println(d); // 2

double dd = 3.7;
int ii = (int) dd; // Bisogna convertire esplicitamente il tipo double in int!
System.out.println(ii); // 3, la parte decimale è stata scartata

Spesso questo sorprende — perché dopo la conversione la parte decimale è sparita? Semplicemente perché il tipo int non può memorizzare frazioni (tutto ciò che viene dopo il punto scompare per sempre).

Maggiori dettagli sulla conversione da double a int e sull’operatore (int) nella prossima lezione.

7. Output formattato: stampiamo double in modo elegante

Spesso, di default, un double viene stampato con un sacco di zeri superflui. Possiamo formattare l’output:

double temp = 23.56789;
System.out.println(temp); // 23.56789

// 2 cifre decimali
System.out.println(String.format("%.2f", temp)); // 23.57

// 1 cifra decimale
System.out.println(String.format("%.1f%n", temp)); // 23.6
Formato Risultato Descrizione
"%.2f"
23.57 numero con 2 cifre decimali
"%.1f"
23.6 numero con 1 cifra decimale

8. Errori tipici nell’uso di float e double

Errore n. 1: conversione implicita da double a float

float f = 1.23; // Errore!

Il compilatore non sarà contento: «Stai cercando di mettere double in float — questo può portare a perdita di precisione!» Aggiungi sempre il suffisso f.

Errore n. 2: hai dimenticato che la divisione di due int dà un risultato int

int a = 7, b = 2;
double result = a / b; // 3.0, non 3.5

Per ottenere la parte decimale, converti esplicitamente almeno uno degli operandi:

double result = (double) a / b; // 3.5

Errore n. 3: confronto di numeri a virgola mobile

Non confrontare numeri a virgola mobile per l’uguaglianza usando ==. Usa un confronto con una piccola tolleranza (epsilon).

Errore n. 4: perdita di precisione con float

Non memorizzare numeri grandi o valori molto precisi in float — potrebbero «rompersi» o perdere cifre importanti.

1
Compito
JAVA 25 SELF, livello 6, lezione 2
Bloccato
Calcolo della velocità media della nave spaziale 🚀
Calcolo della velocità media della nave spaziale 🚀
1
Compito
JAVA 25 SELF, livello 6, lezione 2
Bloccato
Accettazione del pagamento in un distributore automatico intelligente 💰
Accettazione del pagamento in un distributore automatico intelligente 💰
1
Compito
JAVA 25 SELF, livello 6, lezione 2
Bloccato
Formattazione dei prezzi nella vetrina di un negozio online 🛍️
Formattazione dei prezzi nella vetrina di un negozio online 🛍️
1
Compito
JAVA 25 SELF, livello 6, lezione 2
Bloccato
Divisione delle mele magiche tra amici-avventurieri 🍎
Divisione delle mele magiche tra amici-avventurieri 🍎
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION