Menu

La classe Math in Java: pow, sqrt, abs, round, random e altro

Come usare la classe Math di Java: Math.pow, Math.sqrt, Math.abs, Math.max e Math.min, arrotondare con round, floor e ceil, generare numeri casuali in un intervallo con Math.random e le costanti PI ed E, con il tipo di ritorno di ciascuno.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

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 riga import da scrivere.
  • Ogni metodo è static. Lo chiami sul nome della classe, Math.sqrt(25), e non crei mai un oggetto Math. La pagina sui membri statici spiega cosa significa static.

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.

MetodoCosa faRestituisce
Math.pow(a, b)a elevato alla bdouble
Math.sqrt(x)radice quadratadouble
Math.cbrt(x)radice cubicadouble
Math.abs(x)valore assolutolo stesso tipo di x
Math.max(a, b) / Math.min(a, b)il maggiore / il minore dei dueil più ampio dei due tipi
Math.round(x)intero più vicinolong per un double, int per un float
Math.floor(x) / Math.ceil(x)arrotonda per difetto / per eccessodouble
Math.random()numero casuale da 0.0 fino a 1.0double
Math.PI, Math.Ele costanti π ed edouble

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.round va all'intero più vicino. Un valore esattamente a metà viene arrotondato verso l'alto, verso l'infinito positivo, quindi 2.5 diventa 3 e -2.5 diventa -2. Restituisce un long per un argomento double (e un int per un float).
  • Math.floor arrotonda sempre per difetto, verso l'infinito negativo, e restituisce un double.
  • Math.ceil arrotonda sempre per eccesso, verso l'infinito positivo, e restituisce un double.
  • 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:

  1. Math.random() * 6 dà un double da 0.0 fino a 6.0 escluso.
  2. (int) elimina la parte decimale e dà uno tra 0, 1, 2, 3, 4, 5.
  3. + 1 lo sposta a 1, 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 di b, che è ciò che serve per ricominciare da capo in un intervallo come i giorni della settimana. L'operatore % mantiene il segno di a.
  • I metodi trigonometrici (sin, cos, tan) accettano radianti. Converti prima i gradi con Math.toRadians.
  • Math.addExact, Math.multiplyExact e i metodi simili lanciano una ArithmeticException in 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.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA