Ejemplo de Sobrecarga: Números Complejos

La Clase Complex

Este ejemplo esta tomado de Rosetta Code (Complex Class in Groovy):

generaciondecodigos@nereida:~/src/groovy/overloading$ cat -n Complex.groovy 
 1  class Complex {                                                     
 2      final Number real, imag                                         
 3                                                                      
 4      static final Complex I = [0,1] as Complex                       
 5                                                                      
 6      Complex(Number real) { this(real, 0) }                          
 7                                                                      
 8      Complex(real, imag) {                                           
 9         this.real = real; this.imag = imag                           
10      }                                                               
11                                                                      
12      Complex plus (Complex c) { [real + c.real, imag + c.imag] as Complex }
13                                                                            
14      Complex plus (Number n) { [real + n, imag] as Complex }               
15                                                                            
16      Complex minus (Complex c) { [real - c.real, imag - c.imag] as Complex }
17                                                                             
18      Complex minus (Number n) { [real - n, imag] as Complex }               
19                                                                             
20      Complex multiply (Complex c) { [real*c.real - imag*c.imag , imag*c.real + real*c.imag] as Complex }
21                                                                                                         
22      Complex multiply (Number n) { [real*n , imag*n] as Complex }                                       
23                                                                                                         
24      Complex div (Complex c) { this * c.recip() }                                                       
25                                                                                                         
26      Complex div (Number n) { this * (1/n) }                                                            
27                                                                                                         
28      Complex negative () { [-real, -imag] as Complex }                                                  
29                                                                                                         
30      /** the complex conjugate of this complex number.                                                  
31        * Overloads the bitwise complement (~) operator. */                                              
32      Complex bitwiseNegate () { [real, -imag] as Complex }                                              
33                                                                                                         
34      /** the magnitude of this complex number. */                                                       
35     // could also use Math.sqrt( (this * (~this)).real )                                                
36      Number abs () { Math.sqrt( real*real + imag*imag ) }                                               
37                                                                                                         
38      /** the complex reciprocal of this complex number. */                                              
39      Complex recip() { (~this) / ((this * (~this)).real) }                                              
40                                                                                                         
41      /** derived angle θ; (theta) for polar form.                                                 
42        * Normalized to [0, 2 * π] */                                              
43      Number getTheta() {                                                                                
44          def theta = Math.atan2(imag,real)                                                              
45          theta = theta < 0 ? theta + 2 * Math.PI : theta                                                
46      }                                                                                                  
47                                                                                                         
48      /** derived magnitude ρ; (rho) for polar form. */                                            
49      Number getRho() { this.abs() }                                                                     
50                                                                                                         
51      /** Runs Euler's polar-to-Cartesian complex conversion,                                            
52        * converting [ρ, θ] inputs into a [real, imag]-based complex number */             
53      static Complex fromPolar(Number rho, Number theta) {                                               
54          [rho * Math.cos(theta), rho * Math.sin(theta)] as Complex                                      
55      }                                                                                                  
56                                                                                                         
57      /** Creates new complex with same magnitude π;, but different angle θ; */              
58      Complex withTheta(Number theta) { fromPolar(this.rho, theta) }
59
60      /** Creates new complex with same angle θ;, but different magnitude ρ; */
61      Complex withRho(Number rho) { fromPolar(rho, this.theta) }
62
63      static Complex exp(Complex c) { fromPolar(Math.exp(c.real), c.imag) }
64
65      static Complex log(Complex c) { [Math.log(c.rho), c.theta] as Complex }
66
67      Complex power(Complex c) {
68          this == 0 && c != 0  \
69                  ?  [0] as Complex  \
70                  :  c == 1  \
71                          ?  this  \
72                          :  exp( log(this) * c )
73      }
74
75      Complex power(Number n) { this ** ([n, 0] as Complex) }
76
77      boolean equals(other) {
78          other != null && (other instanceof Complex \
79                                  ? [real, imag] == [other.real, other.imag] \
80                                  : other instanceof Number && [real, imag] == [other, 0])
81      }
82
83      int hashCode() { [real, imag].hashCode() }
84
85      String toString() {
86          def realPart = "${real}"
87          def imagPart = imag.abs() == 1 ? "i" : "${imag.abs()}i"
88          real == 0 && imag == 0 \
89                  ? "0" \
90                  : real == 0 \
91                          ? (imag > 0 ? '' : "-")  + imagPart \
92                          : imag == 0 \
93                                  ? realPart \
94                                  : realPart + (imag > 0 ? " + " : " - ")  + imagPart
95      }
96  }

Programa Cliente

generaciondecodigos@nereida:~/src/groovy/overloading$ cat -n useComplex.groovy 
 1  #!/usr/bin/env groovy                                                  
 2
 3  def tol = 0.000000001  // tolerance: acceptable "wrongness" to account for rounding error
 4
 5  println 'Demo 1: functionality as requested'
 6  def a = [5,3] as Complex
 7  println 'a == ' + a
 8  def b = [0.5,6] as Complex
 9  println 'b == ' + b
10
11  println "a + b == (${a}) + (${b}) == " + (a + b)
12  println "a * b == (${a}) * (${b}) == " + (a * b)
13  assert a + (-a) == 0
14  println "-a == -(${a}) == " + (-a)
15  assert (a * a.recip() - 1).abs() < tol
16  println "1/a == (${a}).recip() == " + (a.recip())
17  println()
18
19  println 'Demo 2: other functionality not requested, but important for completeness'
20  println "a - b == (${a}) - (${b}) == " + (a - b)
21  println "a / b == (${a}) / (${b}) == " + (a / b)
22  println "a ** b == (${a}) ** (${b}) == " + (a ** b)
23  println 'a.real == ' + a.real
24  println 'a.imag == ' + a.imag
25  println 'a.rho == ' + a.rho
26  println 'a.theta == ' + a.theta
27  println 'a*~a == ' + a*~a
28  println 'sqrt(a*~a) == ' + (a*~a).power(0.5)
29  println '|a| == ' + a.abs()
30  println 'a_bar == ' + ~a
31
32  def rho = 10
33  def piOverTheta = 3
34  def theta = Math.PI / piOverTheta
35  def fromPolar1 = Complex.fromPolar(rho, theta)          // direct polar-to-cartesian conversion
36  def fromPolar2 = Complex.exp(Complex.I * theta) * rho     // Euler's equation
37  println "rho*cos(theta) + rho*i*sin(theta) == ${rho}*cos(pi/${piOverTheta}) +  ${rho}*i*sin(pi/${piOverTheta}) == " + fromPolar1
38  println "rho * exp(i * theta) == ${rho} * exp(i * pi/${piOverTheta}) == " + fromPolar2
39  assert (fromPolar1 - fromPolar2).abs() < tol
40  println()

Ejecución

generaciondecodigos@nereida:~/src/groovy/overloading$ ./useComplex.groovy | cat -n
 1  Demo 1: functionality as requested
 2  a == 5 + 3i
 3  b == 0.5 + 6i
 4  a + b == (5 + 3i) + (0.5 + 6i) == 5.5 + 9i
 5  a * b == (5 + 3i) * (0.5 + 6i) == -15.5 + 31.5i
 6  -a == -(5 + 3i) == -5 - 3i
 7  1/a == (5 + 3i).recip() == 0.1470588235 - 0.0882352941i
 8
 9  Demo 2: other functionality not requested, but important for completeness
10  a - b == (5 + 3i) - (0.5 + 6i) == 4.5 - 3i
11  a / b == (5 + 3i) / (0.5 + 6i) == 0.56551724145 - 0.78620689665i
12  a ** b == (5 + 3i) ** (0.5 + 6i) == -0.013750112198456855 - 0.09332524760169053i
13  a.real == 5
14  a.imag == 3
15  a.rho == 5.830951894845301
16  a.theta == 0.5404195002705842
17  a*~a == 34
18  sqrt(a*~a) == 5.830951894845301
19  |a| == 5.830951894845301
20  a_bar == 5 - 3i
21  rho*cos(theta) + rho*i*sin(theta) == 10*cos(pi/3) +  10*i*sin(pi/3) == 5.000000000000001 + 8.660254037844386i
22  rho * exp(i * theta) == 10 * exp(i * pi/3) == 5.000000000000001 + 8.660254037844386i



Subsecciones
Casiano Rodríguez León
2010-04-30