Mathematical explanation and step-by-step implementation guide
What is the Mandelbrot Set?
The Mandelbrot set is a mathematical set of complex numbers that produces beautiful fractal patterns when visualised.
It was discovered by Benoit Mandelbrot in 1980 and has become one of the most famous examples of mathematical beauty.
The set is defined by a surprisingly simple iterative formula applied to complex numbers, yet it produces infinitely complex patterns.
What makes it special is that you can zoom into the boundary forever and keep finding new intricate structures at every scale.
The Mathematics
Complex Numbers Review
Complex numbers have the form a + bi, where:
a is the real part (horizontal position)
b is the imaginary part (vertical position)
i is the imaginary unit where i² = -1
To multiply complex numbers: (a + bi)(c + di) = (ac - bd) + (ad + bc)i
The Mandelbrot Formula
For each complex number c, we test whether it belongs to the Mandelbrot set by repeatedly applying this formula:
zn+1 = zn² + c
Starting with z₀ = 0, we calculate:
z₁ = z₀² + c = 0² + c = c
z₂ = z₁² + c = c² + c
z₃ = z₂² + c = (c² + c)² + c
and so on...
The Membership Test
Key Concept: A complex number c is in the Mandelbrot set if the sequence stays bounded (doesn't "escape to infinity") as we iterate forever.
In practice, we use two rules to decide if a number is in the set:
Escape condition: If |z| > 2 at any point, the sequence will definitely escape to infinity. The number is NOT in the set.
Iteration limit: If we've done many iterations (e.g., 100) and |z| is still ≤ 2, we assume the number IS in the set.
Note: The magnitude |z| of a complex number z = a + bi is calculated as √(a² + b²)
Worked Example
Let's test whether c = 0.3 + 0.5i is in the Mandelbrot set:
For this value, |z| remains less than 2 throughout many iterations, so c = 0.3 + 0.5i is in the Mandelbrot set.
Colouring and Visualisation
The beautiful colours you see in Mandelbrot images aren't part of the mathematical set itself — the Mandelbrot set is typically shown as dark!
The colours represent how quickly points outside the set escape to infinity:
Dark pixels: Points in the set (never escape)
Coloured pixels: Points outside the set — colour indicates how many iterations before escape
Lighter colours: Typically points that escape quickly (few iterations)
Darker colours: Points that take many iterations to escape
The main Mandelscope explorer uses "Smooth Periodic Wave Colouring" which creates fluid rainbow patterns by using
the final iteration count and the magnitude of z to generate smooth, continuous colour transitions.
Why Complex Numbers?
Complex numbers are essential because they give us a 2D space to explore. The real part of c corresponds
to the x-axis (horizontal position), and the imaginary part corresponds to the y-axis (vertical position). This allows us to
visualise the set as an image where each pixel represents testing a different complex number.
Connection to Julia Sets
Julia sets are closely related to the Mandelbrot set: instead of fixing z₀ = 0 and varying c, we fix
c to a specific value and vary z₀. Each point in the Mandelbrot set corresponds to a different Julia set.
Points inside the Mandelbrot set produce connected Julia sets, while points outside produce disconnected "dust" Julia sets.
You can explore Julia sets in the main Mandelscope application by clicking on any point in the Mandelbrot view!
The Algorithm
Pseudocode
Here's the algorithm in language-independent pseudocode:
FUNCTION mandelbrot(c_real, c_imag, max_iterations)
// c_real: real part of c
// c_imag: imaginary part of c
// max_iterations: how many times to iterate before giving up
z_real = 0
z_imag = 0
FOR iteration FROM 0 TO max_iterations
// Calculate magnitude squared: |z|²
magnitude_squared = z_real * z_real + z_imag * z_imag
// Check if escaped (using |z|² > 4 instead of |z| > 2 to avoid sqrt)
IF magnitude_squared > 4 THEN
RETURN iteration // Escaped after 'iteration' steps
END IF
// Calculate z² = (z_real + z_imag*i)²
// Using: (a + bi)² = (a² - b²) + (2ab)i
new_real = z_real * z_real - z_imag * z_imag
new_imag = 2 * z_real * z_imag
// Add c to get z² + c
z_real = new_real + c_real
z_imag = new_imag + c_imag
END FOR
RETURN max_iterations // Didn't escape - probably in the set
END FUNCTION
FUNCTION drawMandelbrot(width, height, max_iterations)
// Define the region of the complex plane to view
x_min = -2.5
x_max = 1.0
y_min = -1.25
y_max = 1.25
FOR each pixel row y FROM 0 TO height
FOR each pixel column x FROM 0 TO width
// Map pixel coordinates to complex plane
c_real = x_min + (x / width) * (x_max - x_min)
c_imag = y_min + (y / height) * (y_max - y_min)
// Test if this point is in the Mandelbrot set
iterations = mandelbrot(c_real, c_imag, max_iterations)
// Color the pixel
IF iterations == max_iterations THEN
setPixel(x, y, DARK_COLOR) // In the set
ELSE
setPixel(x, y, LIGHT_COLOR) // Not in the set
END IF
END FOR
END FOR
END FUNCTION
Key Implementation Details
Coordinate mapping: We map pixel coordinates (0 to width/height) to complex plane coordinates (e.g., -2.5 to 1.0)
Optimization: We check |z|² > 4 instead of |z| > 2 to avoid calculating square roots (since (√x)² = x, and 2² = 4)
Iteration count: Typical values are 50-500. Higher values show more detail but take longer to compute
The region: The standard view shows real values from -2.5 to 1.0, imaginary values from -1.25 to 1.25
Working Implementation
Here's a complete, minimal implementation in JavaScript using a 2D canvas.
This code draws a simple two-color Mandelbrot set with no additional features.
600×450 pixels, 100 iterations per point
JavaScript Implementation
✏️ Editable Code: Try modifying the code below and click "Run Code" to see your changes!
💡 Try These Experiments:
Change maxIterations to 50 or 200 to see how detail changes
Modify the viewing window (xMin, xMax, yMin, yMax) to zoom in
Change the colors: try '#ff5555', '#88ff88', or experiment with different hex codes
Add a third color for points that escape quickly: if (iterations < 10) ctx.fillStyle = '#999';
Make the canvas smaller (e.g., 300×225) to see it draw faster
Understanding the Output
In the image above, you should see:
Dark blue regions: Points that are IN the Mandelbrot set (never escaped)
Cyan regions: Points that are NOT in the set (escaped to infinity)
The main cardioid: The large bulbous dark shape in the center
The circular bulb: The circular dark region to the left of the cardioid
Smaller bulbs: Tiny circular structures around the main shape
Tip: The boundary between dark and light is where the interesting fractal patterns emerge.
In the main Mandelscope explorer, we use colors to show HOW QUICKLY points escape, revealing beautiful detail.
Extending the Basic Implementation
Once you understand this basic implementation, you can add many enhancements:
Smooth coloring: Use the iteration count to assign colors, creating the rainbow patterns you see in the main explorer
Zooming: Allow users to zoom into regions by adjusting xMin, xMax, yMin, yMax
Panning: Let users drag to move around the complex plane
Higher precision: For extreme zoom levels, you need arbitrary-precision arithmetic (like the main explorer uses)
GPU acceleration: Move the calculation to the GPU using WebGL shaders for real-time performance
Julia sets: Instead of fixing z₀=0 and varying c, fix c and vary z₀ to generate Julia sets
Computational Complexity
For an image of W×H pixels with maximum M iterations per point:
Time complexity: O(W × H × M) - we test every pixel up to M times
Space complexity: O(W × H) - we need to store the image data
For a 600×450 image with 100 iterations, that's up to 27 million operations!
This is why the main Mandelscope explorer uses GPU acceleration - graphics cards can perform these calculations in parallel across thousands of cores.
Try It Yourself
Exercise: Try modifying the code above to:
Change the viewing window (xMin, xMax, yMin, yMax) to zoom into different regions
Increase maxIterations to 200 or 500 to see more detail (warning: will be slower!)
Add grayscale coloring: map the iteration count to different shades of gray
Draw only the boundary: color pixels differently only if they escape within a certain iteration range
Further Learning
Next steps in your Mandelbrot journey:
Research the escape time algorithm for smooth coloring
Learn about complex dynamics and how the formula relates to iteration stability
Explore Julia sets - the "siblings" of the Mandelbrot set
Study perturbation theory to understand deep zooming (used in the main explorer)
Investigate other fractals: Burning Ship, Newton fractals, Lyapunov fractals