Parte sesta: matematica con Java - Digilander

Parte sesta: matematica con Java
In questa parte prenderemo in esame la classe Math del package java.lang. Vedremo come
utilizzarne i vari metodi ed attributi. In questa parte continueremo a sviluppare il progetto visto
nella parte precedente, cioè la creazione della classe NewMath, che simuli il funzionamento della
classe Math già esistente. Alla fine di questo corso avremo un’applicazione funzionante, anche più
amplia di quella originale.
1. La classe Math: una panoramica
Come abbiamo già detto, la classe Math è contenuta nel package java.lang ed è una classe finale.
Non possono quindi essere estese nuove classi. Inoltre il metodo costruttore di Math è ad accesso
privato (non possono essere create istanze) e tutti i suoi metodi sono statici. Alcuni metodi di questa
classe sono anche nativi. Vedremo cosa sono i metodi nativi più avanti nel corso. Vediamo un
esempio: se volessimo richiamare il metodo sqrt() per calcolare la radice quadrata di 9
scriveremmo:
Math.sqrt(9);
Vediamo rapidamente i metodi e gli attributi di questa classe:
Metodo / attributo
Descrizione
long abs(long l)
Restituisce il valore assoluto del numero specificato
float abs(float f)
Restituisce il valore assoluto del numero specificato
double abs(double d)
Restituisce il valore assoluto del numero specificato
int abs(int i)
Restituisce il valore assoluto del numero specificato
double acos(double d)
Restituisce l’arcocoseno del numero specificato
double asin(double d)
Restituisce l’arcoseno del numero specificato
double atan(double d)
Restituisce l’arcotangente del numero specificato
double ceil(double d)
Restituisce il valore intero minimo maggiore o
uguale al numero specificato
double cos(double d)
Restituisce il coseno del numero specificato
double exp(double d)
Restituisce il numero e (numero di Nepero) elevato
ad
double floor(double d)
Restituisce il valore intero massimo minore o uguale
al numero specificato
double log(double d)
Restituisce il logaritmo del numero specificato
int max(int i, int i1)
long max(long l, long l1)
float max(float f, float f1)
double max(double d, double d1)
int min(int i, int i1)
long min(long l, long l1)
float min(float f, float f1)
double min(double d, double d1)
double pow(double d, double d1)
double random()
int round(float f)
long round(double d)
Restituisce
specificati
Restituisce
specificati
Restituisce
specificati
Restituisce
specificati
Restituisce
specificati
Restituisce
specificati
Restituisce
specificati
Restituisce
specificati
il numero maggiore fra i due numeri
il numero maggiore fra i due numeri
il numero maggiore fra i due numeri
il numero maggiore fra i due numeri
il numero minore fra i due numeri
il numero minore fra i due numeri
il numero minore fra i due numeri
il numero minore fra i due numeri
Eleva a potenza, con base d ed esponente d1
Restituisce un numero pseudocasuale compreso fra
0e1
Arrotonda il numero specificato all’intero più
prossimo
Arrotonda il numero specificato all’intero più
prossimo
double sin(double d)
Restituisce il seno del numero specificato
double sqrt(double d)
Restituisce la radice quadrata del numero specificato
double tan(double d)
Restituisce la tangente del numero specificato
double E
double PI
Restituisce il valore del numero di Nepero,
equivalente a 2.7182818284590451
Restituisce il valore di π, equivalente a
3.1415926535897931
Vediamo un esempio: calcolare il quadrato del seno di un angolo α e sommarlo al quadrato del
coseno dello stesso angolo α. La notazione matematica è la seguente: sin 2 α + cos 2 α . Supponendo
che il valore dell’angolo α sia 45: sin 2 45 + cos 2 45 . Traduciamo l’espressione in Java:
double d = Math.pow(Math.sin(45), 2) + Math.pow(Math.cos(45), 2);
Il risultato dell’espressione riportata sopra è 1.0.
Vediamo un altro esempio: la tangente di un angolo α è data dal rapporto fra il seno ed il coseno
dello stesso angolo α. Verificare se la suddetta affermazione corrisponde al vero. Dalla
sin α
affermazione sopra, deduciamo che tan α =
. Per verificare, proviamo a tradurre l’espressione
cos α
matematica in Java, utilizzando ancora come valore di α 45:
double d1 = Math.tan(45);
double d2 = Math.sin(45) / Math.cos(45);
if(d1 == d2)
System.out.println("Affermazione vera.");
else
System.out.println("Affermazione falsa.");
Il risultato è “Affermazione vera.”.
Vediamo adesso come ampliare la classe NewMath.
2. Ampliamo la classe NewMath
Per aggiungere un metodo utile alla nostra classe, consideriamo il seguente problema: nella classe
Math originale non è definito alcun metodo che calcoli una radice superiore a quella quadrata.
Come risolviamo questo problema? E’ ben noto il concetto matematico secondo il quale ogni
2
numero è in realtà una frazione. Ad esempio, 2 può essere scritto anche
. La notazione
1
matematica per indicare un elevamento a potenza è y x . Ma questa notazione può anche essere
x
1
scritta così: y 1 . Se invertiamo dell’esponente il denominatore con il suo numeratore, otteniamo y x .
1
Se proviamo, ad esempio, ad elevare 9 a ½ otteniamo che 9 2 è uguale a 3. Abbiamo quindi estratto
la radice quadrata di 9 tramite un elevamento a potenza. Quindi affermiamo che elevando un
numero y per un’esponente con numeratore 1 e con denominatore x eseguiamo l’estrazione di
radice con indice x e radicando y. Viceversa, estraendo radice di un radicando y con un indice
frazionario avente 1 per numeratore ed x per denominatore, eseguiamo l’elevamento a potenza di
un numero y con esponente x. In termini matematici scriveremo:
1
y = y x . Possiamo quindi creare
un metodo che calcoli queste radici servendoci dell’esistente metodo pow().
public static double root(double d, double d1)
{
return Math.pow(d, 1 / d1);
}
x
Adesso proveremo a creare dei metodi che simulino alcune funzionalità della classe Math. Non
analizzeremo tutti i metodi, in quanto, alcuni, eseguono calcoli complessi.
Elevamento a potenza: possiamo dare la seguente definizione matematica per l’elevamento a
potenza di un numero:
xn = 1
 n
 x = nd
 n
n −1
x = x ⋅ x
se n = 0 e x ≠ 0
se n = 0 e x = 0
se n > 0 e x ≠ 0
Per risolvere questo problema potremmo utilizzare una funzione ricorsiva. Esaminiamo il codice del
metodo seguente:
public static double power(double base, double exp)
{
if(base != 0 && exp == 0)
return 1;
else
if(base == 0 && exp == 0)
return 0;
else
return power(base, exp - 1) * base;
}
Notiamo che il metodo controlla i valori che gli vengono passati come parametri per distinguere i
casi specifici ed il caso generale.
Valore assoluto:
public static int absolute(int i)
{
if(i == 0)
return 0;
else
if(i > 0)
return i;
else
return -i;
}
public static double absolute(double d)
{
if(d == 0)
return 0;
else
if(d > 0)
return d;
else
return -d;
}
public static float absolute(float f)
{
if(f == 0)
return 0;
else
if(f > 0)
return f;
else
return -f;
}
public static long absolute(long l)
{
if(l == 0)
return 0;
else
if(l > 0)
return l;
else
return -l;
}
Esistono altri metodi che possono essere aggiunti, ma, per adesso, ci fermeremo qui. Prenderemo
ancora in considerazione le funzioni matematiche più avanti nel corso e nella parte dedicata alle
animazioni ed al disegno e anche nella parte dedicata a Java Native Interface (JNI). Nella prossima
parte vedremo le stringhe in dettaglio, utilizzando anche le classi StringBuffer e StringTokenizer.