1. "Hello, World!"
  2. Variables and Types
  3. Arrays
  4. While, If, For
  5. ...Problem Set 0
  6. Static Methods
  7. Static Fields
  8. String Conversion
  9. Objects
  10. Threading
  11. Strings
  12. ...Problem Set 1.5
  13. Packages
  14. Complex Numbers
  15. Abstract classes
  16. Interfaces
  17. Autoboxing
  18. ...Problem Set 1
  19. enum
  20. Inner Classes
  21. Polymorphism
  22. Tanks!
  23. Callbacks
  24. Exceptions
  25. File I/O
  26. ...Problem Set 2
  27. Regular Expressions

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
1public class ComplexCart {
2    // data hiding
3    private double reim;
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 + rec.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
1public 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
1public class ComplexPolar {
2    // data hiding
3    private double radang;
4 
5    // Constructor
6    public ComplexPolar(double raddouble 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?