1. Arrotondamento dei numeri reali
Come abbiamo già discusso, quando un numero reale viene assegnato a una int
variabile, viene sempre arrotondato per difetto all'intero più piccolo più vicino: la parte frazionaria viene semplicemente scartata.
Ma è facile immaginare una situazione in cui un numero frazionario deve essere arrotondato all'intero più vicino in entrambe le direzioni o addirittura arrotondato per eccesso. Cosa fai in questo caso?
Per questo e per molte situazioni simili, Java ha la Math
classe, che ha i metodi round()
, ceil()
e floor()
.
Math.round()
metodo
Il Math.round()
metodo arrotonda un numero all'intero più vicino:
long x = Math.round(real_number)
Ma c'è un'altra sfumatura qui: questo metodo restituisce un long
numero intero (non un int
). Poiché i numeri reali possono essere molto grandi, i creatori di Java hanno deciso di utilizzare il tipo intero più grande disponibile di Java: long
.
Di conseguenza, se un programmatore desidera assegnare il risultato a una int
variabile, deve indicare esplicitamente al compilatore che accetta l'eventuale perdita di dati (nel caso in cui il numero risultante non rientri in un int
tipo).
int x = (int) Math.round(real_number)
Esempi:
Dichiarazione | Risultato |
---|---|
|
|
|
|
|
|
Math.ceil()
metodo
Il Math.ceil()
metodo arrotonda un numero per eccesso a un numero intero. Ecco alcuni esempi:
Dichiarazione | Risultato |
---|---|
|
|
|
|
|
|
Math.floor()
metodo
Il Math.floor()
metodo arrotonda un numero per difetto a un numero intero. Ecco alcuni esempi:
Dichiarazione | Risultato |
---|---|
|
|
|
|
|
|
Naturalmente, quando si arrotonda un numero per difetto a un numero intero, è più semplice utilizzare semplicemente un operatore di cast di tipo:(int)
Dichiarazione | Risultato |
---|---|
|
|
Se trovi difficile ricordare questi nomi, una breve lezione di inglese ti aiuterà:
Math
significa matematicaRound
significa rotondoCeiling
significa soffittoFloor
significa pavimento
2. Come sono strutturati i numeri in virgola mobile
Il double
tipo può memorizzare valori nell'intervallo da a . Questa vasta gamma di valori (rispetto al tipo) è spiegata dal fatto che il tipo (così come ) ha una struttura interna completamente diversa rispetto ai tipi interi. Internamente, il tipo codifica il proprio valore come due numeri: il primo è chiamato mantissa e il secondo è chiamato esponente .-1.7*10308
+1.7*10308
int
double
float
double
Diciamo che abbiamo il numero 123456789
e lo memorizziamo come double
variabile. Quando lo facciamo, il numero viene convertito in e internamente il tipo memorizza due numeri — e . Il significante ("parte significativa del numero" o mantissa) è evidenziato in rosso, mentre l'esponente è evidenziato in blu.1.23456789*108
double
23456789
8
Questo approccio consente di memorizzare sia numeri molto grandi che numeri molto piccoli. Ma poiché la rappresentazione del numero è limitata a 8 byte (64 bit) e alcuni dei bit vengono utilizzati per memorizzare l' esponente (così come il segno della mantissa e il segno dell'esponente), le cifre massime disponibili per rappresentare la mantissa è 15 .
Questa è una descrizione molto semplificata di come sono strutturati i numeri reali.
3. Perdita di precisione quando si lavora con numeri reali
Quando lavori con i numeri reali, tieni sempre presente che i numeri reali non sono esatti . Potrebbero esserci sempre errori di arrotondamento ed errori di conversione durante la conversione da decimale a binario. Inoltre, la fonte di errore più comune è la perdita di precisione durante l'aggiunta/sottrazione di numeri su scale radicalmente diverse.
Quest'ultimo fatto è un po' strabiliante per i programmatori alle prime armi.
Se sottraiamo da , otteniamo .1/109
109
109
Sottrarre numeri su scale radicalmente diverse | Spiegazione |
---|---|
|
Il secondo numero è estremamente piccolo , il che farà sì che il suo significato (evidenziato in grigio) venga ignorato. Le 15 cifre significative sono evidenziate in arancione. |
Cosa possiamo dire, la programmazione non è la stessa cosa della matematica.
4. Insidia quando si confrontano numeri reali
Un altro pericolo attende i programmatori quando confrontano i numeri reali. Sorge quando si lavora con numeri reali, perché possono accumularsi errori di arrotondamento. Il risultato è che ci sono situazioni in cui ci si aspetta che i numeri reali siano uguali, ma non lo sono. O viceversa: i numeri dovrebbero essere diversi, ma sono uguali.
Esempio:
Dichiarazione | Spiegazione |
---|---|
|
Il valore della variabile a sarà 1000000000.0 Il valore della variabile c sarà 1000000000.0 (il numero nella b variabile è eccessivamente piccolo) |
Nell'esempio precedente, a
e c
non dovrebbero essere uguali, ma lo sono.
Oppure facciamo un altro esempio:
Dichiarazione | Spiegazione |
---|---|
|
Il valore della variabile a sarà 1.0 Il valore della variabile b sarà1.0 |
5. Un fatto interessante sustrictfp
Java ha una strictfp
parola chiave speciale ( strict f loating point ), che non si trova in altri linguaggi di programmazione. E sai perché ne hai bisogno? Peggiora la precisione delle operazioni con numeri in virgola mobile. Ecco la storia di come è nato:
GO TO FULL VERSION