# Mandelbrot Set Miscalculations

While developing a Java program to create an image of the Mandelbrot set, I stumbled upon a small error which completely changes the set’s look. To fix this bug, you need to swap two lines of code.

The bug arises when trying to convert convenient Python features to Java.
To iteratively apply the function $z \to z^2 + c$, you update your complex number $z$ a certain amount of times. When you are not using a complex number class, but instead you use two floating point numbers (in Java doubles to gain precision) $\texttt{a}$ and $\texttt{b}$ to define the real and imaginary part $(z = \texttt{a} + \texttt{b} \cdot i)$, logically both numbers need to be updated.
In Python you may write the following, when $c$ is defined as being a complex number with parts $\texttt{c}$ and $\texttt{d}$ $(c = \texttt{c} + \texttt{d})$.

a, b = a**2 - b**2 + c, 2 * a * b + d

Which seems to be very similar to those two lines.

a = a**2 - b**2 + c
b = 2 * a * b + d

But notice that in the first code snippet you define a tuple consisting of the real and imaginary part and then assign it to the variables. The first snippet really looks like this.

t = (a**2 - b**2 + c, 2 * a * b + d)
a, b = t

Using this assignment of variables, which corresponds to $z \to z^2 + c$, you get an image of the correct Mandelbrot set.

In contrary, the second code snippet assigns the old $\texttt{a}$ its new value, then uses this new $\texttt{a}$ to define the value of new $\texttt{b}$, thus does not calculate $z \to z^2+c$, which is equivalent to $z \to (\texttt{a}^2-\texttt{b}^2+\texttt{c}) + (2\cdot\texttt{a}\cdot\texttt{b}+\texttt{d}) \cdot i$, but rather $z \to (\texttt{a}^2-\texttt{b}^2+\texttt{c}) + (2 \cdot \texttt{a}^2 \cdot \texttt{b}-2\cdot \texttt{b}^3+2\cdot\texttt{b}\cdot\texttt{c}+\texttt{d})\cdot i$.

In Java it would look like this.

a = a*a - b*b + c;
b = 2 * a * b + d;

Which results in this rather unusual depiction of the famous fractal.

You can easily avoid this bug when using two sets of variables to define old $z$ and new $z$, as shown in the following.

_a = a*a - b*b + c;
_b = 2 * a * b + d;
a = _a;
b = _b;

Or you can define variables $\texttt{asqr} = \texttt{a}^2$ and $\texttt{bsqr} = \texttt{b}^2$ and swap the assignment. Using variables for the squares of the parts of $z$ also helps to improve performance.

b = 2 * a * b + d;
a = asqr - bsqr + c;
asqr = a*a;
bsqr = b*b;


// Java 1.8 Code
// Jonathan Frech, September / November / December 2016



// generates a 1080x720 zoomed out .png
// image of the Mandelbrot Set fractal

// import
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;

// main class
public class mandel {
// main function
public static void main(String[] args) {
// dimensions
int width  = 1080;
int height = 720;

// image
BufferedImage img = new BufferedImage(
width, height, BufferedImage.TYPE_INT_RGB
);

// p1: top left, p2: bottom right
double p1y = -1.2;
double p2y =  1.2;
double p1x = -(p2y - p1y) / 2.0 * width / height - 0.5;
double p2x =  (p2y - p1y) / 2.0 * width / height - 0.5;

// transform pixel coordinates into complex numbers
double facx = (p2x - p1x) / width;
double facy = (p2y - p1y) / height;
double addx = p1x;
double addy = p1y;

// variables needed
double a, b, _a, _b, c, d, asqr, bsqr;
int i;

// go through image pixels
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {

// reset variables
i = -1;
a = 0;
b = 0;
asqr = 0;
bsqr = 0;
c = x * facx + addx;
d = -(y * facy + addy);
// iteratively apply f_c(z) = z*z + c
while (asqr+bsqr <= 4) {
// correct Mandelbrot set
/*
_a = a*a - b*b + c;
_b = 2 * a * b + d;
a = _a;
b = _b;//*/

// Mandelbrot set miscalculation
//*
a = a*a - b*b + c;
b = 2 * a * b + d;//*/

// re(z)**2, im(z)**2
asqr = a*a;
bsqr = b*b;

// increment iterations needed
i++;

// too many iterations needed, abort
if (i >= 255) {
break;
}
}

// set pixel color according to iterations needed
int k = 255 - i;
img.setRGB(x, y, ((k << 16) | (k << 8) | k));
}
}

// save image to disk
try {
File file = new File(
System.getProperty("user.dir") + "/mandel.png"
);
ImageIO.write(img, "png", file);
}
catch(IOException e) {
System.out.println("Error: " + e);
}
}
}
Advertisements

## 2 thoughts on “Mandelbrot Set Miscalculations”

1. Pingback: Mandelbrot Set II – J-Blog

2. Pingback: Multibrot Set – J-Blog

This site uses Akismet to reduce spam. Learn how your comment data is processed.