Complex number class for Processing
This is not a math tutorial. See Why am I writing about math?
https://introcs.cs.princeton.edu/java/97data/Complex.java.html
Basic outline of a complex number class:
class Complex {
float re, im;
Complex(float re, float im) {
this.re = re;
this.im = im;
}
Complex add(Complex other) {
return new Complex(re + other.re, im + other.im);
}
Complex mult(Complex other) {
return new Complex(
re * other.re - im * other.im,
re * other.im + im * other.re
);
}
float magnitude() {
return sqrt(re*re + im*im);
}
}
With the hint that “divide() is a bit tricker. It involves multiplying by the conjugate.”
And the further hint when I Google (ask Google AI at this point), “What does it mean to multiply by the conjugate?”
Multiplying by the conjugate means changing the sing (+ to - or - to +) in a binomial expression (like a + b becomes b + a) and then multiplying, which uses the difference of the squares formula:
(a + b)(a - b) = a^2 - b^2
This process simplifies expressions, especially by removing radicals or imaginary parts from denominators (rationalizing the denominator). It eliminates the middle terms, resulting in simpler expressions, often a real number.
To simplify a complex number like 4 + 7i, multiply by its conjugate 4 - 7i:
(4+7i)(4-7i)=4^{2}-(7i)^{2}=16-49i^{2}=16-49(-1)=16+49=65
Processing complex number classes #
1 month later…
I find the polar form easier to think about for multiplication and division, and the rectangular form easier to think about for addition and subtraction. It seems that for most cases it will be more efficient to work with the rectangular form. Efficiency isn’t necessarily the goal though.
In any case, here’s a ComplexPolar and a ComplexRect class. The code is sort of texted, just by
comparing the results of some calculations with similar calculations made in Python.
class ComplexPolar {
double r, theta;
ComplexPolar(double r, double theta) {
this.r = r;
this.theta = theta;
}
ComplexPolar mult(ComplexPolar other) {
return new ComplexPolar(r * other.r, theta + other.theta);
}
ComplexPolar divide(ComplexPolar other) {
if (Math.abs(other.r) < 1e-10) {
return new ComplexPolar(Double.POSITIVE_INFINITY, theta - other.theta);
}
return new ComplexPolar(r / other.r, theta - other.theta);
}
ComplexPolar scalarMult(double s) {
return new ComplexPolar(r * s, theta);
}
ComplexPolar scalarDivide(double s) {
if (Math.abs(s) < 1e-10) {
return new ComplexPolar(Double.POSITIVE_INFINITY, theta);
}
return new ComplexPolar(r / s, theta);
}
ComplexPolar power(double n) {
return new ComplexPolar(Math.pow(r, n), theta * n);
}
ComplexPolar add(ComplexPolar other) {
double re = this.re() + other.re();
double im = this.im() + other.im();
double magnitude = Math.sqrt(Math.pow(re, 2) + Math.pow(im, 2));
double angle = Math.atan2(im, re);
return new ComplexPolar(magnitude, angle);
}
ComplexPolar subtract(ComplexPolar other) {
double re = this.re() - other.re();
double im = this.im() - other.im();
double magnitude = Math.sqrt(Math.pow(re, 2) + Math.pow(im, 2));
double angle = Math.atan2(im, re);
return new ComplexPolar(magnitude, angle);
}
ComplexPolar scalarAdd(double s) {
double re = this.re() + s;
double im = this.im();
double magnitude = Math.sqrt(Math.pow(re, 2) + Math.pow(im, 2));
double angle = Math.atan2(im, re);
return new ComplexPolar(magnitude, angle);
}
ComplexPolar scalarSubtract(double s) {
double re = this.re() - s;
double im = this.im();
double magnitude = Math.sqrt(Math.pow(re, 2) + Math.pow(im, 2));
double angle = Math.atan2(im, re);
return new ComplexPolar(magnitude, angle);
}
ComplexRect toRect() {
double re = r * Math.cos(theta);
double im = r * Math.sin(theta);
return new ComplexRect(re, im);
}
double re() {
return r * Math.cos(theta);
}
double im() {
return r * Math.sin(theta);
}
}
class ComplexRect {
double re, im;
ComplexRect(double re, double im) {
this.re = re;
this.im = im;
}
ComplexRect add(ComplexRect other) {
return new ComplexRect(re + other.re, im + other.im);
}
ComplexRect scalarAdd(double s) {
return new ComplexRect(re + s, im);
}
ComplexRect subtract(ComplexRect other) {
return new ComplexRect(re - other.re, im - other.im);
}
ComplexRect scalarSubtract(double s) {
return new ComplexRect(re - s, im);
}
ComplexRect mult(ComplexRect other) {
return new ComplexRect(
re * other.re - im * other.im,
re * other.im + im * other.re
);
}
ComplexRect scalarMult(double s) {
return new ComplexRect(re * s, im * s);
}
ComplexRect divide(ComplexRect other) {
double denominator = Math.pow(other.re, 2) + Math.pow(other.im, 2);
if (Math.abs(denominator) < 1e-10) {
return new ComplexRect(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
}
double real = (re * other.re + im * other.im) / denominator;
double imaginary = (im * other.re - re * other.im) / denominator;
return new ComplexRect(real, imaginary);
}
ComplexRect scalarDivide(double s) {
if (Math.abs(s) < 1e-10) {
return new ComplexRect(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
}
double real = re / s;
double imaginary = im / s;
return new ComplexRect(real, imaginary);
}
ComplexRect power(double n) {
ComplexPolar z = this.toPolar();
ComplexPolar zn = z.power(n);
return zn.toRect();
}
ComplexPolar toPolar() {
double r = Math.sqrt(Math.pow(re, 2) + Math.pow(im, 2));
double theta = Math.atan2(im, re);
return new ComplexPolar(r, theta);
}
double magnitude() {
return Math.sqrt(Math.pow(re, 2) + Math.pow(im, 2));
}
}