Una cassetta degli attrezzi di metodi statici
java.lang.Math è una classe piena di funzioni matematiche pronte all'uso: potenze, radici, valori assoluti, arrotondamenti, trigonometria, logaritmi e numeri casuali. Due cose la rendono facile da usare:
- Si trova in
java.lang, che ogni file Java importa automaticamente. Non c'è nessuna rigaimportda scrivere. - Ogni metodo è
static. Lo chiami sul nome della classe,Math.sqrt(25), e non crei mai un oggettoMath. La pagina sui membri statici spiega cosa significastatic.
Nota che alcuni risultati vengono stampati con .0 e altri no. Ogni metodo di Math ha un tipo di ritorno fisso, e conoscerlo è gran parte di ciò che c'è da imparare su questa classe.
| Metodo | Cosa fa | Restituisce |
|---|---|---|
Math.pow(a, b) | a elevato alla b | double |
Math.sqrt(x) | radice quadrata | double |
Math.cbrt(x) | radice cubica | double |
Math.abs(x) | valore assoluto | lo stesso tipo di x |
Math.max(a, b) / Math.min(a, b) | il maggiore / il minore dei due | il più ampio dei due tipi |
Math.round(x) | intero più vicino | long per un double, int per un float |
Math.floor(x) / Math.ceil(x) | arrotonda per difetto / per eccesso | double |
Math.random() | numero casuale da 0.0 fino a 1.0 | double |
Math.PI, Math.E | le costanti π ed e | double |
Math.pow: le potenze
Math.pow(base, exponent) eleva un numero a una potenza. Accetta due parametri double e restituisce un double, anche quando passi numeri interi:
Per salvare il risultato in un int, fai un cast con (int). Per piccole potenze intere il risultato double è esatto, quindi il cast dà la risposta giusta. È con i risultati grandi che il cast sbaglia: un double oltre Integer.MAX_VALUE (2.147.483.647) diventa esattamente Integer.MAX_VALUE, quindi (int) Math.pow(2, 40) dà 2147483647. Per potenze più grandi fai il cast a long, e ricorda che oltre 2⁵³ un double non riesce a rappresentare esattamente ogni numero intero. La pagina sul type casting spiega cosa fa un cast al valore.
Java non ha un operatore di potenza. 2 ^ 3 compila, ma ^ è lo XOR bit a bit e il risultato è 1, non 8. È uno dei bug più comuni dei principianti nel codice matematico in Java.
Un double da dieci milioni in su viene stampato in notazione scientifica, cosa che sorprende chi stampa per la prima volta una potenza di dieci:
1.0E7 significa 1.0 × 10⁷. Il valore è lo stesso; cambia solo la forma stampata. Fai il cast a long, oppure formatta con String.format("%.0f", value), per stamparlo come cifre normali.
Math.sqrt e Math.cbrt: le radici
Math.sqrt(x) restituisce la radice quadrata di x come double. Math.cbrt(x) restituisce la radice cubica.
La radice quadrata di un numero negativo non è un numero reale, quindi Math.sqrt(-4) restituisce NaN ("not a number", non è un numero) invece di lanciare un'eccezione. NaN si propaga in qualsiasi calcolo in cui compare, quindi controlla gli input prima di calcolare una radice se sono possibili valori negativi. Math.hypot(a, b) calcola direttamente sqrt(a*a + b*b), un modo comune per ottenere la distanza tra due punti.
Math.abs: il valore assoluto
Math.abs(x) toglie il segno. A differenza di pow e sqrt, restituisce lo stesso tipo che gli passi: un int per un int, un double per un double.
L'uso tipico è una differenza in cui conta la grandezza, non la direzione, come la distanza tra due posizioni.
Math.max e Math.min
Math.max(a, b) restituisce il maggiore di due valori e Math.min(a, b) il minore. Accettano esattamente due argomenti. Per tre o più, annida le chiamate:
Quando i due argomenti hanno tipi diversi, il più stretto viene prima allargato. Math.max(3, 7.5) confronta due valori double e restituisce un double. L'ultimo esempio blocca un valore nell'intervallo da 0 a 100: Math.min lo limita a 100, Math.max gli impedisce di scendere sotto 0.
Arrotondare: round, floor, ceil
Java ha tre metodi di arrotondamento, e differiscono sia nella direzione sia nel tipo di ritorno:
Math.roundva all'intero più vicino. Un valore esattamente a metà viene arrotondato verso l'alto, verso l'infinito positivo, quindi2.5diventa3e-2.5diventa-2. Restituisce unlongper un argomentodouble(e unintper unfloat).Math.floorarrotonda sempre per difetto, verso l'infinito negativo, e restituisce undouble.Math.ceilarrotonda sempre per eccesso, verso l'infinito positivo, e restituisce undouble.- Un cast
(int)non è affatto un arrotondamento: elimina la parte decimale, il che sposta i numeri positivi verso il basso e quelli negativi verso l'alto.
Poiché Math.round(double) restituisce un long, assegnarlo a un int non compila senza un cast:
int n = Math.round(2.6); // error: incompatible types: possible lossy conversion from long to int
int m = (int) Math.round(2.6); // OK, m vale 3
long k = Math.round(2.6); // OK
Per arrotondare a un certo numero di cifre decimali, moltiplica, arrotonda e poi dividi di nuovo. Dividere per 100.0 (un double) invece che per 100 mantiene i decimali:
La seconda riga divide un long per un int, cioè una divisione intera, quindi i decimali vanno persi. Quando ti serve solo mostrare un numero arrotondato, String.format("%.2f", value) è più semplice e non cambia il valore memorizzato.
Math.random: numeri casuali
Math.random() restituisce un double maggiore o uguale a 0.0 e minore di 1.0. Il valore cambia a ogni chiamata, quindi l'output dei programmi di questa sezione cambia ogni volta che premi Run.
Per ottenere un numero intero in un intervallo, allarga quel valore, fai il cast e spostalo. Per un numero intero da min a max, entrambi inclusi:
int value = (int) (Math.random() * (max - min + 1)) + min;
Ecco come funziona per un dado, dove min è 1 e max è 6:
Math.random() * 6dà undoubleda0.0fino a6.0escluso.(int)elimina la parte decimale e dà uno tra0, 1, 2, 3, 4, 5.+ 1lo sposta a1, 2, 3, 4, 5, 6.
La prima riga mostra cinque lanci casuali. La seconda controlla diecimila lanci e, in pratica, stampa sempre lowest: 1, highest: 6: la formula raggiunge entrambi gli estremi dell'intervallo e non li supera mai.
Le parentesi intorno a Math.random() * (max - min + 1) sono importanti. Un cast si applica al valore subito dopo, quindi (int) Math.random() * 6 converte prima Math.random(). Il risultato è sempre 0, e 0 * 6 è 0, quindi ogni "lancio" dà lo stesso numero.
Math.random() va bene per giochi ed esercizi. Per qualcosa di più, la classe java.util.Random e ThreadLocalRandom.current().nextInt(min, max + 1) (in java.util.concurrent) restituiscono direttamente degli interi, e Random può ricevere un seed per ripetere la stessa sequenza nei test. Nessuno di questi è adatto a password o token di sicurezza; per quelli usa java.security.SecureRandom.
Math.PI e Math.E
Math.PI (π) e Math.E (il numero di Eulero e) sono costanti static final double:
Usale invece di scrivere 3.14. Sono precise quanto consente un double, e il nome dice a chi legge che numero è.
Risultati interi e risultati double
La maggior parte dei metodi di Math accetta e restituisce double. Quando gli passi valori int, Java allarga automaticamente gli argomenti a double, ma i calcoli che scrivi prima della chiamata avvengono comunque in int. È da qui che arriva la maggior parte delle risposte sbagliate:
items / perBox è 7 / 2, e dividere due valori int scarta il resto, quindi vale 3 prima ancora che Math.ceil lo veda. Math.ceil(3.0) è 3.0. Rendi double uno degli operandi, con un cast o con un letterale come 4.0, così la divisione mantiene la parte decimale. La pagina sugli operatori spiega la divisione intera più nel dettaglio.
La regola generale: decidi quale tipo vuoi alla fine, fai avvenire la divisione o la moltiplicazione in double quando i decimali contano, e fai il cast a int o long una sola volta, alla fine.
Altri metodi utili
Qualche altro metodo della stessa classe, tutti chiamati allo stesso modo:
Math.logè il logaritmo naturale;Math.log10è in base 10.Math.floorMod(a, b)dà un resto con il segno dib, che è ciò che serve per ricominciare da capo in un intervallo come i giorni della settimana. L'operatore%mantiene il segno dia.- I metodi trigonometrici (
sin,cos,tan) accettano radianti. Converti prima i gradi conMath.toRadians. Math.addExact,Math.multiplyExacte i metodi simili lanciano unaArithmeticExceptionin caso di overflow invece di passare silenziosamente a un numero negativo.
Domande frequenti
Come si usa Math.pow in Java?
Math.pow(base, exponent) restituisce base elevato a exponent come double, quindi Math.pow(2, 3) vale 8.0. Per salvare il risultato in un int, fai un cast: int n = (int) Math.pow(2, 10); dà 1024. Java non ha un operatore di potenza ^: ^ è lo XOR bit a bit.
Come genero un numero casuale in un intervallo con Math.random?
Math.random() restituisce un double da 0.0 fino a 1.0 escluso. Per un numero intero da min a max, entrambi inclusi, usa (int) (Math.random() * (max - min + 1)) + min. Un lancio di dado è (int) (Math.random() * 6) + 1.
Devo importare la classe Math in Java?
No. Math si trova nel package java.lang, che ogni file Java importa automaticamente. Tutti i suoi metodi sono static, quindi li chiami sul nome della classe, come in Math.sqrt(16), senza creare alcun oggetto.
Perché Math.round restituisce un long in Java?
Math.round(double) restituisce un long perché un double può contenere valori molto più grandi di un int. Per assegnare il risultato a un int serve un cast: int n = (int) Math.round(2.6);. Math.round(float) restituisce un int.
Che differenza c'è tra Math.floor, Math.ceil e Math.round?
Math.floor arrotonda per difetto (2.7 diventa 2.0, -2.3 diventa -3.0), Math.ceil arrotonda per eccesso (2.1 diventa 3.0) e Math.round va all'intero più vicino, con le metà arrotondate verso l'alto (2.5 diventa 3). floor e ceil restituiscono un double; round restituisce un long.