Complex Numbers
One of the standard classes that people like to create, both as an example and for practical purposes, is the
complex number.
For those of you who are not familiar with the concept, the idea is that we use "i" to represent an "imaginary number",
namely the square root of negative one. One then writes a complex number as "3+4*i" and say that the "real part" of
the complex number is 3, and the "imaginary part" of the complex number is four.
Here are some examples of multiplication using complex numbers:
i*i = -1 |
(1+i)*(1+i) = 1 + i + i + i*i = 2*i |
(1+2*i)*(3+4*i) = 1+6*i+4*i+8*i*i = -5+10*i |
A complex number is like a point on a graph -- the real part is the x value and the imaginary part is the y value.
As you learned in math class (I hope), you can make a graph with either Cartesian coordinates or polar coordinates.
The polar coordinate version of the complex number can be found using the following mystical equation:
exp(i*ang) = cos(ang)+i*sin(ang) |
Here is a first implementation of the complex number using the "Cartesian" representation.
ComplexCart.java |
1 | public class ComplexCart { |
2 | // data hiding |
3 | private double re, im; |
4 | |
5 | // Constructor |
6 | public ComplexCart(double re,double im) { |
7 | this.re = re; // keyword this |
8 | this.im = im; |
9 | } |
10 | |
11 | public double re() { return re; } // real part |
12 | public double im() { return im; } // complex part |
13 | public double rad() { return Math.sqrt(re*re+im*im); } |
14 | |
15 | // atan2 is a type of arc tangent that takes two arguments, y and x. |
16 | // This is much less ambiguous than a simple ratio. |
17 | // atan2(-1, 1)*180/pi = -45 |
18 | // atan2( 1,-1)*180/pi = 135 |
19 | public double ang() { return Math.atan2(im,re); } |
20 | |
21 | public ComplexCart add(ComplexCart c) { |
22 | return new ComplexCart(c.re + re, c.im + im); |
23 | } |
24 | |
25 | public ComplexCart mul(ComplexCart c) { |
26 | return new ComplexCart(c.re*re-c.im*im,c.re*im+c.im*re); |
27 | } |
28 | |
29 | // special string conversion method |
30 | public String toString() { |
31 | return "("+re+"+"+im+"i)"; |
32 | } |
33 | public static void main(String[] args) { |
34 | ComplexCart a = new ComplexCart(3,4); |
35 | ComplexCart b = new ComplexCart(5,12); |
36 | ComplexCart c = a.add(b); // c = a + b |
37 | ComplexCart d = c.mul(b); // d = (a + b)*b |
38 | System.out.println("a="+a); |
39 | System.out.println("b="+b); |
40 | System.out.println("c="+c); |
41 | System.out.println("d="+d); |
42 | } |
43 | } |
$ javac ComplexCart.java
| $ java ComplexCart
a=(3.0+4.0i)
b=(5.0+12.0i)
c=(8.0+16.0i)
d=(-152.0+176.0i)
|
Notice the use of "private." Private is a magic word that hides the internal data of ComplexCart from
the outside world.
GetPrivate.java |
1 | public class GetPrivate { |
2 | public static void main(String[] args) { |
3 | ComplexCart cc = new ComplexCart(1,1); |
4 | System.out.println("real part: "+cc.re); |
5 | } |
6 | } |
$ javac GetPrivate.java
GetPrivate.java:4: re has private access in ComplexCart
System.out.println("real part: "+cc.re);
^
1 error
| $ java GetPrivate
Exception in thread "main" java.lang.NoClassDefFoundError: GetPrivate
Caused by: java.lang.ClassNotFoundException: GetPrivate
at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:334)
Could not find the main class: GetPrivate. Program will exit.
|
This concept (private) is one of the magical things which makes objects great. It means that ComplexCart is
really a black box. We have no idea what goes on inside of it, and at some later point we can change its guts
and make it work completely differently -- and if all the public methods work no one will be the wiser.
One of the keys to successful coding is the ability to modularize code, to be able to separate the pieces of
logic so that you can modify individual parts of the tapestry of code without tearing the whole fabric.
To demonstrate this principle, we now re-implement the same class using "polar coordinates."
ComplexPolar.java |
1 | public class ComplexPolar { |
2 | // data hiding |
3 | private double rad, ang; |
4 | |
5 | // Constructor |
6 | public ComplexPolar(double rad, double ang) { |
7 | this.rad = rad; |
8 | this.ang = ang; |
9 | } |
10 | |
11 | public double re() { return rad*Math.cos(ang); } |
12 | public double im() { return rad*Math.sin(ang); } |
13 | public double rad() { return rad; } |
14 | public double ang() { return ang; } |
15 | |
16 | public ComplexPolar add(ComplexPolar c) { |
17 | double rev = re()+c.re(); |
18 | double imv = im()+c.im(); |
19 | double radv = Math.sqrt(rev*rev+imv*imv); |
20 | double angv = Math.atan2(imv,rev); |
21 | return new ComplexPolar(radv,angv); |
22 | } |
23 | |
24 | public ComplexPolar mul(ComplexPolar c) { |
25 | return new ComplexPolar(c.rad*rad,ang+c.ang); |
26 | } |
27 | |
28 | // special string conversion method |
29 | public String toString() { |
30 | return "("+re()+","+im()+"i)"; |
31 | } |
32 | public static void main(String[] args) { |
33 | ComplexPolar a = new ComplexPolar(5,Math.atan2(4,3)); |
34 | ComplexPolar b = new ComplexPolar(13,Math.atan2(12,5)); |
35 | ComplexPolar c = a.add(b); // c = a + b |
36 | ComplexPolar d = c.mul(b); // d = (a + b)*b |
37 | System.out.println("a="+a); |
38 | System.out.println("b="+b); |
39 | System.out.println("c="+c); |
40 | System.out.println("d="+d); |
41 | } |
42 | } |
$ javac ComplexPolar.java
| $ java ComplexPolar
a=(3.0000000000000004,3.9999999999999996i)
b=(4.999999999999998,12.0i)
c=(7.999999999999998,16.000000000000004i)
d=(-152.00000000000009,175.99999999999991i)
|
You may notice some very small differences in the printed results. Don't worry about them. These are the result of "roundoff error." It turns
out that computers cannot perfectly represent real numbers. Instead, they must work with a finite amount of
precision. The complexities and vagaries of how these computer numbers are similar to and different from the real
numbers is beyond the scope of this course.
Wasn't that fun? What can we do with it?
|