La classe NumeroComplesso presenta una interessante implementazione: la gestione interna permette di utilizzare a seconda dei metodi lo stato più appropriato per effettuare i calcoli. Pertanto vengono memorizzati sia la forma cartesiana che la forma trigonometrica dell'oggetto numero complesso.
La forma cartesiana identifica il numero nelle componenti parte reale e coefficiente della parte complessa.
La forma trigonometrica identifica il numero nel suo modulo o norma e l'anomalia o argomento.
Per scelta l'argomento principale é compreso tra -π e +π.
L'Argomento viene ricavato in base al valore relativo k in modo che Arg(z)=arg(z)+2kπ.
Ulteriori miglioramenti devono essere implementati per mantenere coerente lo stato dell'oggetto e per ritornare lavori compresi sempre tra -π e +π.
Classi: esercizio1.java | NumeroComplesso.java
package corsoDrZito.lez2.es1; public class esercizio1 { public static void main(String[] args) { esercizio1 app = new esercizio1(); app.run(); } void run() { NumeroComplesso a = new NumeroComplesso(1.0, 0.0); NumeroComplesso b = new NumeroComplesso(0.0, 1.0); NumeroComplesso c = new NumeroComplesso(1.0, Math.PI, 1); // Pi+2Pi NumeroComplesso zero = new NumeroComplesso(0.0, 0.0); NumeroComplesso unouno = new NumeroComplesso(1.0, 1.0); System.out.println( "Parte reale, coefficiente parte immaginaria, modulo, argomento, argomento principale"); System.out.println( "Re ("+ a +") = "+ a.Re()); System.out.println( "Im ("+ a +") = "+ a.Im()); System.out.println( "Ro ("+ a +") = "+ a.Ro()); System.out.println( "arg("+ a +") = "+ a.arg()); System.out.println( "Arg("+ c +") = "+ c.Arg()); System.out.println( "arg("+ c +") = "+ c.arg()); System.out.println( "\nOperazioni unarie"); System.out.println( "Coniugato "+ b +" = "+ b.coniugato() ); System.out.println( "Reciproco "+ unouno +" = "+ unouno.reciproco() ); System.out.println( "Reciproco "+ unouno +" = "+ unouno.reciproco() ); System.out.println( "\nOperazioni binarie"); System.out.println( "Addizione : "+ a +" + "+ b +" = "+ a.addizione(b) ); System.out.println( "Sottrazione : "+ a +" - "+ b +" = "+ a.sottrazione(b) ); System.out.println( "Prodotto : "+ b +" * "+ c +" = "+ b.prodotto(c) ); try { System.out.println( "Divisione : "+ b +" / "+ c +" = "+ b.divisione(c) ); System.out.println( "Divisione : "+ a +" / "+ zero +" = "+ a.divisione(zero) ); } catch (ArithmeticException e) { System.out.println( e ); } try { System.out.println( "\nOperazioni potenza intera e radice complessa"); System.out.println( "Potenza : "+ unouno +" ^ 2 = "+ unouno.potenza(2) ); System.out.println( "Potenza : "+ a +" ^ 0 = "+ a.potenza(0) ); System.out.println( "Potenza : "+ zero +" ^-3 = "+ zero.potenza(-3) ); } catch (ArithmeticException e) { System.out.println( e ); } NumeroComplesso i = new NumeroComplesso(0.0, 1.0); NumeroComplesso[] radici = NumeroComplesso.radice( i , 3 ); System.out.println( "Radici terze di "+ i); for(int k=0; k<radici.length; k++) System.out.println( "radice "+ k +" = "+ radici[k] ); System.out.println( (radici[2].theta + 2*radici[2].k*Math.PI + Math.IEEEremainder(radici[2].theta + 2*radici[2].k*Math.PI, 2 * Math.PI)) / Math.PI ); } }
package corsoDrZito.lez2.es1; public class NumeroComplesso { double re, im; // parte reale e coefficiente parte immaginaria forma cartesiana: z = a + i b double ro, theta; // modulo e argomento principale forma Trigonometrica: z = ro(cos theta + i sen theta) // ro in [0,+oo[ , -Pi < theta <= Pi int k = 0; // argomento = theta + 2 k Pi boolean inFormaCartesiana; // stato attuale public NumeroComplesso(double re, double im) { this.re = re; this.im = im; inFormaCartesiana = true; coerenza(); } public NumeroComplesso(double ro, double theta, int k) { this.ro = ro; this.theta = theta; this.k = k; inFormaCartesiana = false; coerenza(); } public double Re() { if(!inFormaCartesiana) return ro * Math.cos( theta ); return re; } public double Im() { if(!inFormaCartesiana) return ro * Math.sin( theta ); return im; } public double Ro() { if(inFormaCartesiana) return Math.sqrt( re*re + im*im ); return ro; } public double Arg() { if(inFormaCartesiana) return Math.atan2( im , re ) + 2.0 * k * Math.PI; return theta + 2.0 * k * Math.PI; } public double arg() { if(inFormaCartesiana) return Math.atan2( im , re ); return theta; } public NumeroComplesso coniugato() { if(inFormaCartesiana) im = -im; else theta = -theta; return this; } public NumeroComplesso addizione(NumeroComplesso z) { if(!inFormaCartesiana) coerenza(); if(!z.inFormaCartesiana) z.coerenza(); re += z.re; im += z.im; return this; } public NumeroComplesso sottrazione(NumeroComplesso z) { if(!inFormaCartesiana) coerenza(); if(!z.inFormaCartesiana) z.coerenza(); re -= z.re; im -= z.im; return this; } public NumeroComplesso prodotto(NumeroComplesso z) { if(inFormaCartesiana) { if(!z.inFormaCartesiana) z.coerenza(); double temp; temp = re * z.re - im * z.im; im = re * z.im + im * z.re; re = temp; } else { if(z.inFormaCartesiana) z.coerenza(); ro *= z.ro; theta += z.theta; } return this; } public NumeroComplesso reciproco() throws ArithmeticException { if(inFormaCartesiana) { double temp = re * re + im * im; if (temp==0) throw new ArithmeticException("reciproco di zero"); re /= temp; im /= temp; } else { if (ro == 0.0) throw new ArithmeticException("reciproco di zero"); ro = 1.0 / ro; theta = - theta; } return this; } public NumeroComplesso divisione(NumeroComplesso z) throws ArithmeticException { if(inFormaCartesiana) { if(!z.inFormaCartesiana) z.coerenza(); double temp = z.re * z.re + z.im * z.im; if (temp==0) throw new ArithmeticException("divisione per zero"); re = ( re * z.re + im * z.im ) / temp; im = ( im * z.re - re * z.im ) / temp; } else { if (ro == 0.0) throw new ArithmeticException(); ro /= z.ro; theta -= z.theta; } return this; } public NumeroComplesso potenza(int exp) throws ArithmeticException { if(inFormaCartesiana) coerenza(); if ((ro==0.0)&&(exp<=0)) throw new ArithmeticException("potenza di zero con esponente negativo"); ro = Math.pow(ro, exp); theta *= exp; //k = exp; return this; } public static NumeroComplesso[] radice(NumeroComplesso w, int n) throws ArithmeticException { if(n<=0) throw new ArithmeticException("radice con esponente negativo o nullo"); NumeroComplesso[] radici = new NumeroComplesso[n]; if(w.inFormaCartesiana) w.coerenza(); double ro = Math.pow(w.ro, 1.0d / n); for(int i=0; i<n; i++) radici[i] = new NumeroComplesso( ro, (w.theta + 2 * i * Math.PI)/n, w.k); return radici; } public static NumeroComplesso[] radice2(NumeroComplesso w, int n) throws ArithmeticException { if(n<=0) throw new ArithmeticException("radice con esponente negativo o nullo"); NumeroComplesso[] radici = new NumeroComplesso[n]; if(w.inFormaCartesiana) w.coerenza(); double ro = Math.pow(w.ro, 1.0d / n); for(int i=0; i<n; i++) { double theta = (w.theta + 2 * i * Math.PI)/n; double remainder = Math.IEEEremainder( theta, 2*Math.PI ); int k = (int)((theta + remainder) / Math.PI); radici[i] = new NumeroComplesso( ro, remainder, k); } return radici; } /** rende coerente lo stato interno settando le variabili relative alla forma cartesiana o alla forma trigonometrica */ private void coerenza() { if(inFormaCartesiana) { inFormaCartesiana = false; ro = Math.sqrt( re * re + im * im ); if (ro == 0.0) theta = 0.0; // maybe NaN? else theta = Math.atan2( im , re ); } else { inFormaCartesiana = true; re = ro * Math.cos( theta ); im = ro * Math.sin( theta ); } } public String toString() { if (inFormaCartesiana) return ""+ re +((im>=0.0)? "+" : "")+ im +"j"; else { String k2pi = (k!=0 ? "+"+2*k+"Pi" : ""); return ""+ ro +" ( cos "+ theta + k2pi +" + j sen "+ theta + k2pi +")"; } } }