Complex Numbers in Java

By Xah Lee. Date:

Java does not have complex numbers. Here is a toy function that provides complex number multiplication.

class T2 {

    /**
     * complex number multiplication
     * @param a First complex number to be multiplied
     * @param b Second complex number to be multiplied
     * @return The product of a and b.
     */
    public double[] complexMultiply (double[] a, double[] b) {
        double[] prod= {a[0]*b[0] - a[1]*b[1], a[1]*b[0] + a[0]*b[1]};
        return prod;
    }
}

public class T1 {
    public static void main(String[] arg) {

        double[] c1 ={0., 1.};
        double[] c2 ={0., 1.};

        T2 x1 = new T2();
        double[] m =x1.complexMultiply(c1,c2);
        System.out.println(m[0]); // -1.0
        System.out.println(m[1]); // 0.0
    }
}

A Robust Complex Number Implementation

Here is a more robust, yet still simple, complex number implementation. From David Eck and Richard Palais. http://3D-XplorMath.org/j/index.html.

Note that, in the above, we used array of 2 elements to represent complex numbers. This is a functional approach. While in the code below, a more traditional OOP approach is used.

Go thru it, and see how in general complex numbers are implemented in Java. Try to write a sample code that calls this class and do a multiplication of two complex numbers.

package vmm.core;

/**
 * A complex number, with a real and an imaginary part.  (Possibley to be replaced with
 * a class that has better support for complex arithmetic and functions of a complex variable.)
 */
public class Complex {

  public double re, im;

  /**
   * Create a complex number initially equal to zero
   */
  public Complex() {
  }

  /**
   * Create a complex number initially equal to the real number x.
   */
  public Complex(double x) {
    re = x;
  }

  /**
   * Create a complex number initially equal to x + iy
   */
  public Complex(double x, double y) {
    re = x;
    im = y;
  }

  /**
   * Create a new complex number that is initially equal to a given complex number.
   * @param c The complex number to be copied.  If null, it is treated as zero.
   */
  public Complex(Complex c) {
    copy(c);
  }

  public static final Complex ZERO_C = new Complex(0,0);

  public static final Complex ONE_C = new Complex(1,0);

  public static final Complex I_C = new Complex(0,1);

  /**
   * Returns true if obj is equal to this complex number.  If obj is null or is not
   * of type Complex, the return value is false.
   */
  public boolean equals(Object obj) {
    try {
      Complex c = (Complex)obj;
      return c.re == re && c.im == im;
    }
    catch (Exception e) {
      return false;
    }
  }

  /**
   * Computes the conjugate of a complex number.
   */
  public Complex conj() {
    return new Complex( re, -im );
  }

  /**
   * Returns the complex number (r*cos(theta)) + i*(r*sin(theta)).
   */
  public static Complex polar(double r, double theta) {
    return new Complex(r*Math.cos(theta),r*Math.sin(theta));
  }

  /**
   * Sets this complex number equal to a copy of a given number.
   * @param c The number to be copied; if null, the number is treated as zero.
   */
  public void copy(Complex c) {
    if (c == null)
      re = im = 0;
    else {
      re = c.re;
      im = c.im;
    }
  }

  /**
   * Returns this + c; c must be non-null.
   */
  public Complex plus(Complex c) {
    return new Complex(re + c.re, im + c.im);
  }

  /**
   * Returns this - c; c must be non-null.
   */
  public Complex minus(Complex c) {
    return new Complex(re - c.re, im - c.im);
  }

  /**
   * Returns this * c; c must be non-null.
   */
  public Complex times(Complex c) {
    return new Complex(re*c.re - im*c.im, re*c.im + im*c.re);
  }

  /**
   * Returns this / c; c must be non-null.
   */
  public Complex dividedBy(Complex c) {
    double denom = c.re*c.re + c.im*c.im;
    if (denom == 0)
      return new Complex(Double.NaN,Double.NaN);
    else
      return new Complex( (re*c.re+im*c.im)/denom, (im*c.re-re*c.im)/denom);
  }

  public Complex times(double x) {
    return new Complex(re*x, im*x);
  }

  public Complex plus(double x) {
    return new Complex(re+x, im);
  }

  public Complex minus(double x) {
    return new Complex(re-x, im);
  }

  public Complex dividedBy(double x) {
    return new Complex(re/x, im/x);
  }
  /**
   * Returns the absolute value squared of this.
   * @return real part squared plus imaginary part squared
   */
  public double abs2() {
    return (re*re + im*im);
  }

  /**
   * Returns the absolute value, "r" in polar coordinates, of this.
   * @return the square root of (real part squared plus imaginary part squared)
   */
  public double r() {
    return Math.sqrt(re*re + im*im);
  }

  /**
   * Returns arg(this), the angular polar coordinate of this complex number, in the range -pi to pi.
   * The return value is simply Math.atan2(imaginary part, real part).
   */
  public double theta() {
    return Math.atan2(im,re);
  }

  /**
   * Computes the complex exponential function, e^z, where z is this complex number.
   */
  public Complex exponential() {
    double length = Math.exp(re);
    return new Complex( length*Math.cos(im), length*Math.sin(im) );
  }

  /**
   * Computes the complex reciprocal function, 1/z, where z is this complex number.
   */
  public Complex inverse() {
     double length = re*re+im*im;
    return new Complex( re/length, -im/length );
  }

  public Complex log() {
    double modulus = Math.sqrt(re*re + im*im);
    double arg = Math.atan2(im,re);
    return new Complex(Math.log(modulus), arg);
  }

  /**
   * Computes that complex logarithm of this complex number
   * that is nearest to previous.
   * A test code is in fractals.TestAnalyticContinuation.
   */
  public Complex logNearer(Complex previous) {
    Complex c = new Complex(this.log());
    double h = (c.im - previous.im)/(2*Math.PI);
    double d = (2*Math.PI)*Math.floor(h+0.5);
    c.im = c.im - d;
    return c;
  }

  public double sinh(double x) {
       return (Math.exp(x) - Math.exp(-x))/2;
  }

  public double cosh(double x) {
       return (Math.exp(x) + Math.exp(-x))/2;
  }

  public Complex sine() {
    double x, y;
    Complex z = new Complex(0.0,0.0);
    x = re;
    y = im;
    z.re = Math.sin(x) * cosh(y);
    z.im = Math.cos(x) * sinh(y);
    return z;
  }

  public Complex power(double x) {
    double modulus = Math.sqrt(re*re + im*im);
    double arg = Math.atan2(im,re);
    double log_re = Math.log(modulus);
    double log_im = arg;
    double x_log_re = x * log_re;
    double x_log_im = x * log_im;
    double modulus_ans = Math.exp(x_log_re);
    return new Complex(modulus_ans*Math.cos(x_log_im), modulus_ans*Math.sin(x_log_im));
  }

  /**
   * Returns a complex k-th root of this complex number.  The root that is returned is
   * the one with the smallest positive arg.
   * (If k is 0, the return value is 1.  If k is negative, the value is 1/integerRoot(-k).)
   */
  public Complex integerRoot(int k) {
    double a,b;
    boolean neg = false;
    if (k < 0) {
      k = -k;
      neg = true;
    }
    if (k == 0) {
      a = 1;
      b = 0;
    }
    else if (k == 1) {
      a = re;
      b = im;
    }
    else {
      double length = r();
      double angle = theta();
      if (angle < 0)
        angle += Math.PI*2;
      length = Math.pow(length,1.0/k);
      angle = angle / k;
      a = length*Math.cos(angle);
      b = length*Math.sin(angle);
    }
    if (neg) {
      double denom = a*a + b*b;
      a = a/denom;
      b = -b/denom;
    }
    return new Complex(a,b);
  }

  /**
   * Computes that square root of this complex number
   * that is nearer to previous than to minus previous.
   * A test code is in fractals.TestAnalyticContinuation.
   */
  public Complex squareRootNearer(Complex previous) {
    Complex c;
    c = this.integerRoot(2);
    if (c.re*previous.re + c.im*previous.im < 0){
      c.re=-c.re;
      c.im=-c.im;
    }
    return new Complex(c.re, c.im);
  }

  public double[] stereographicProjection() {

      double rsquare,rsquarePlusOne;
        double [] projPoint = new double[3];
        rsquare = re * re + im * im;
        rsquarePlusOne = rsquare + 1;
        projPoint[0] = (2 * re)/rsquarePlusOne;
        projPoint[1] = (2 * im)/rsquarePlusOne;
        projPoint[2] = (rsquare - 1)/rsquarePlusOne;
        return projPoint;
      }
}

Java

  1. Install
  2. javac java jar javadoc

Java Basics

  1. Print String
  2. Strings
  3. Power Function
  4. Java Types and Type Conversion
  5. Function
  6. Arrays

Class, Inheritance

  1. extends
  2. Constructor
  3. Constructor Return Type
  4. Extending a Class that has Explicit Constructors
  5. static
  6. this
  7. super
  8. Access Specifiers

Abstract class, Interface

  1. abstract
  2. Interface

Package

  1. Package

Misc

  1. Collection, Map
  2. Read/Write File
  3. Convert File Encoding
  4. Complex Numbers in Java
  5. Unicode
  6. Number Literals