Let’s draw the Mandelbrot set!


When I was 12 or 13 I saw a science program about fractals and chaos theory. I was intrigued by the intricate organic shapes and bright colors, especially of the Mandelbrot set, and decided I wanted to learn how to make them. This is how I got interested in mathematics and programming in the first place. Drawing the Mandelbrot set makes a rewarding exercise for a beginning programmer, covering many important topics like loops and conditional statements.

Zoomed detail of the Mandelbrot set.

Zoomed detail of the Mandelbrot set. Cropped from Wikipedia

Mathematically, the Mandelbrot set is defined on the plane of complex numbers by picking a starting point \(c\) and iterating the formula \(z_{k+1} = z_k^2 + c\). The iteration gives you a sequence of numbers that either stays bounded or spirals out of control further and further from the starting point. The complex number \(c\) belongs to the Mandelbrot set if the sequence stays within a radius of 2 from the origin.

Plotting the Mandelbrot set is easy: map each pixel on the screen to a complex number, check if it belongs to the set by iterating the formula, and color the pixel black if it does and white if it doesn’t. Since the iteration may never end we set a maximum

First of all we need a way to represent complex numbers. Some programming languages like Python include a built-in complex number type which we could use to implement the iteration using the above formula directly. Other languages such as Java or JavaScript don’t include complex numbers, but not to worry: we can represent the complex number \(z = x+iy\) as the pair of real numbers \((x,y)\). In this representation the Mandelbrot set iteration becomes:

\[
\begin{align}
x_{k+1} &= x_k^2 – y_k^2 + \mathrm{Re}\ c \\
y_{k+1} &= 2 x_k y_k + \mathrm{Im}\ c
\end{align}
\]

All that’s left now is figuring out how to map pixels to complex numbers. That’s an easy task: we want the center of the image to be mapped to (0,0), so given a pixel we subtract half of the image height from the vertical coordinate, and half of the width from the horizontal coordinate. Next, the scale: we know that the Mandelbrot set lies within a circle of radius 2, so the entire width of the image should have length 4. This gives us the following program for plotting the Mandelbrot set in a C-like language:

for (int row = 0; row < height; row++) {
    for (int col = 0; col < width; col++) {
        double c_re = (col - width/2.0)*4.0/width;
        double c_im = (row - height/2.0)*4.0/width;
        double x = 0, y = 0;
        int iteration = 0;
        while (x*x+y*y <= 4 && iteration < max) {
            double x_new = x*x - y*y + c_re;
            y = 2*x*y + c_im;
            x = x_new;
            iteration++;
        }
        if (iteration < max) putpixel(col, row, white);
        else putpixel(col, row, black);
    }
}

(You can find an actual implementation in Java in GitHub.) Here’s the plot produced by it:

mandelbrot

That’s not particularly impressive, is it? Where are the pretty colors?

Since the Mandelbrot set has a very fine structure, by plotting only black or white we don’t get any idea of how close a pixel is to the set. The number of iterations gives us some idea of that, so let’s use it to color the pixels that don’t belong to the set. The change needed in the code is trivial: define a color map and use it instead of white:

    if (iterations < max) putpixel(col, row, colors[iterations]);

(Implementation in Java.) The image produced by this program is much prettier and gives a better idea of the structure of the set, with fine tendrils springing from the bulbs.

Mandelbrot set with color

This basic program can be enhanced a lot. Ideally it should be interactive, allowing the user to zoom into different parts of the plot and produce impressive visualization. The aesthetics of the images can be enhanced: in particular the color mapping we have chosen shows discontinuous bands where the iteration count changes. Also, some optimizations can be made to make the program generate the images faster. I’ll treat some of these issues in future posts.

2 Trackbacks

  1. […] Let’s draw the Mandelbrot set! (jonisalonen.com) […]

  2. […] on an interpreter, too separated from the hardware to get top performance. For example, the Mandelbrot set program from my previous post should clearly be faster when written in […]

2 Comments

  1. Joe Z
    Posted 2013/11/19 at 22:28 | Permalink

    I was similarly transfixed by the Mandelbrot in my teens. I once wrote a Mandelbrot generator for my Casio graphing calculator. Ate about $5 in batteries with it. I later spent many hours with FRACTINT, which worked quite a bit better than that slow graphing calculator.

  2. deniz
    Posted 2016/02/25 at 22:41 | Permalink

    I am trying to write a code that draws mandelbrot set. I don’t know why but I just want to :) it didn’t work so far. I have checked some other codes on the net to understand the calculations but they were to complex to understand. but this one is the simplest and the best code I have seen so far. easy to understand and also easy to modify. A magic code :) thank you for sharing.