Zoom into the Mandelbrot set using ordinary computer numbers and, somewhere past a magnification of about 1013, the picture falls apart into flat blocks of colour. Our Mandelbrot deep zoom explorer keeps going. Its deepest built-in view is 4 × 10-1000 units tall: a decimal point followed by 999 zeros before the first digit that matters.
This page explains what you are seeing, why ordinary arithmetic fails, and what the explorer does instead. Equations are kept to one marked section for developers. New to the set? Read What is the Mandelbrot set? first.
Views you can open yourself
Each link opens the explorer at an exact position. Beside it is the full view: the centre (real and imaginary parts), the vertical span, and the iteration budget, which is how many steps each pixel gets before the calculation gives up. The numbers also work in other deep zoom programs such as Fraktaler 3 or Kalles Fraktaler 2+, though the colours will differ.
-
The whole set
A heart-shaped main cardioid, a round bulb on its left, and smaller bulbs all round the edge.
- Real centre
-0.5- Imaginary centre
0- Vertical span
3- Iterations
1024
-
Seahorse Valley
The gap between the main body and the left bulb. Curled, tail-like shapes line both walls.
- Real centre
-0.75- Imaginary centre
0.1- Vertical span
0.04- Iterations
1024
-
Seahorse spirals
Twenty times closer, where the tails wind into spirals.
- Real centre
-0.7435- Imaginary centre
0.1314- Vertical span
0.002- Iterations
4096
-
Deep view at 10-113
Roughly 10113 times closer than the whole set. Each coordinate has 176 decimal places.
- Real centre
-1.47981577613247326072298452597877854692240725774045369689878510139864920741002293820250517329282011227363313053159203914640783415609608168660705123082446357179491909705403381200- Imaginary centre
-0.00063911193261361727152139632255671572957303918943984736047394936471220951961813321928573067036466151147195436388486168819318341208023229522609015461543581599807510715681229605- Vertical span
8E-114- Iterations
35494
-
Deep view at 10-1000
The deepest view in the explorer's menu, with 1,032 decimal places per coordinate.
- Real centre
-1.941576032416438467025801020715296345583631070333763697155363215369995323174821426569343939280976688941799033949553513877360049760854818438847807512062527483938432108334379682374425724538963945203811384410447188902539280186443207724592660257192245282122435497500512116978510994235729842140426212659047449275392649582144536809606048256661942015415293902082484897583908489968914729856261014595046784170486406281774634659010437551209316119397222613229217917022405856521450471398240958803454546592237981445377671184500660547408817261831894272352819877027084299780680294324572817973522425697710448544266296164872469941207915318387606736780997353983062554261604503546149292936642204630313050512074878556249827082472838018479056231300425717628324576406385386489046596333813954944872237432232584712794199385182029966095629800079433529594932724703432396513169426246696336919279357704478424514838526831184178560128965986916218888035003760618018546383024162868702909340031454797870830171151871458976156454695759759455242167153480852905329612928- Imaginary centre
0.007616985717772811262124668760622981437662236623940733858977202402020949904597675982567903438152747187001453792570531900379945655089068104542887520569666325496854943970482334766465568902178471662205610335655386327591088355630793583666899303983220376324437451114866304483466406624113681671822911479962978243988037880036085177763383839177390736670205923960451531786620698624310112277206323661779555548745795026511137379365757720941649670500838538041663501778850301672389321517369030732380361504406649221281161353695980774304817750907225115318738323761935375270212445755332408668293878051992878181731210653759907898838467665702947448379879550359982270646382467980986879289206553850989072075578963952995904652178779463868993619754936296821786991785780531050125323823377470573405525813057794363468880870906692986558129005828655981351971538509527655719324861000343097111273792722058002993775507514675899953901227838493650982772056135274894875568039070393925760084216277141057220628182876163008403838153533411744597352540385947641225916772- Vertical span
4E-1000- Iterations
32000
The two deep views are copied digit for digit from the published test locations of the open-source rust-fractal project (e1000 location file). Expect deep views to take tens of seconds or more with the default engine; see the measurements below.
The formula and the boundary
Every point in the picture stands for a complex number, c: across is the real part, up is the imaginary part. To test a point, start with z = 0 and repeat one step:
For some values of c the numbers stay small forever, and those points belong to the Mandelbrot set. For others they grow without limit. Once the size of z passes 2 it is certain to keep growing, so the point has escaped.
Benoit Mandelbrot's 1980 paper on the iteration z → λz(1 − z) (a scan is hosted at Harvard) studied an equivalent form of this quadratic family. Adrien Douady and John Hubbard's Orsay notes on complex polynomial dynamics built much of the theory.
A computer runs a finite number of steps, so each pixel either escaped, which proves it is outside, or was still small when the budget ran out. That second kind might be inside the set, or might escape on the next step. The explorer paints it dark grey and does not claim it is inside.
The structure sits on the boundary. Points just outside it can take thousands or millions of steps to escape, which is why deep views need large budgets.
What appears as you zoom
Zoom into the boundary and the same few things keep turning up. Thin filaments branch from the edge. Spirals form where filaments wind round a point. Among them sit small copies of the whole set.
The copies are often rotated or squashed, and the decoration around each depends on the route you took to reach it. Not every direction stays interesting: smooth colour outside the set stays smooth, and the grey interior stays grey. A good deep zoom keeps the boundary in view.
That boundary is about as crowded as a curve in the plane can be. Mitsuhiro Shishikura proved that its Hausdorff dimension is 2, the largest possible value. That measures how wrinkled the edge is; it does not make the boundary a filled-in shape.
The boundary also links the set to Julia sets. Every value of c has its own Julia set, and crossing the boundary changes that Julia set from one connected piece to scattered dust. The Julia-Mandelbrot relationship explains that connection.
What the colours mean
The set has no colours of its own. Every colour in the explorer is a choice we made to show how quickly each point escaped.
For an escaped point, the explorer takes the step on which z passed 2 and adds a fractional correction based on how large z had grown, so you see gradients instead of hard bands. Linas Vepstas derived this renormalised escape count. The explorer maps the value onto a palette that repeats every 64 units.
Switch palettes and the picture changes completely while the maths stays the same. Two colours carry fixed meanings: the dark interior tone marks pixels that did not escape within the budget, and plain grey marks pixels still being computed. Points waiting for a repair calculation are painted from their neighbours until the answer arrives; the Exact tier shows them in pale pink instead.
The precision wall
Most software stores numbers as 64-bit floating point values, often called doubles. A double holds about 16 significant decimal digits. Close to -0.75, neighbouring doubles are 2-53 apart, roughly 1.1 × 10-16, and nothing in between can be stored.
Here is what JavaScript's Number() makes of four different decimal strings:
| Decimal text | As a JavaScript number | Equal to Number('-0.75')? |
|---|---|---|
-0.75 | -0.75 | Yes (same text) |
-0.75000000000000001 | -0.75 | Yes |
-0.74999999999999999 | -0.75 | Yes |
-0.7500000000000001 | -0.7500000000000001 | No |
Checked in Node.js: Number('-0.75') === Number('-0.75000000000000001') returns true. The two points are 10-17 apart.
Now picture an image 600 pixels tall. At a span of 10-13, neighbouring pixels are about 1.7 × 10-16 apart, close to the gap between doubles. At a span of 10-15 the pixel spacing shrinks to about 1.7 × 10-18, so around 66 pixels in a row round to the same double and get exactly the same answer. More iterations cannot help: every pixel in a block is computing the same number.
Graphics cards make this worse. WebGL shaders usually work in 32-bit floats, and as Mikael Hvidtfeldt Christensen showed for OpenGL and WebGL, true double precision is not generally available there. Our main visualizer runs on those shaders and caps its zoom at 1014 for this reason.
A second wall sits further down. A double cannot hold a number below about 2.2 × 10-308 at full precision, and in the 10-1000 view even the distance between pixels is far smaller.
How the explorer gets past it
The explorer never squeezes the view into a double. It keeps the centre and span as decimal text, the same text that goes into a shared link, and then relies on four ideas.
One very precise reference point
It runs z → z² + c for one reference point near the centre with arbitrary precision arithmetic, using GNU MPFR compiled to WebAssembly through gmp-wasm. For the 10-1000 view at 600 pixels tall, it asks for 3,464 binary digits, a little over 1,000 decimal places. That is slow, but only for one point.
Every other pixel as a small difference
Each pixel sits very close to the reference, so the explorer only tracks how far the pixel's sequence of z values differs from the reference sequence. Ordinary arithmetic handles that tiny difference well. This is called perturbation. Phil Thompson's illustrated introduction to perturbation walks through the idea step by step.
To go below 10-308, it stores a number's exponent separately from its digits, like scientific notation, so 3.2 × 10-990 is no trouble. Robert Munafo's Mu-Ency entry on floatexp describes this format.
Skipping steps safely
Long runs of steps often change the difference predictably. Bivariate linear approximation (BLA) prepares shortcuts from the reference so one lookup can replace many steps. Phil Thompson's guide to rendering with BLA explains it. In one 256 × 256 render of the 10-113 view, the GPU path did about 489 million ordinary steps and skipped about 1,056 million.
Checking every answer
If a pixel drifts too far from the reference, perturbation loses accuracy and can draw a convincing but wrong pattern, called a glitch. Claude Heiland-Allen's notes on perturbation glitches show what they look like. The GPU engine watches for the warning sign of a glitch, the pixel's orbit falling very close to the reference orbit, and when it sees one it recomputes that pixel with slower, error-tracked arithmetic. Whatever that cannot settle goes to the processor for direct high-precision arithmetic. While those last few points are being checked the explorer already shows the image, painting each unchecked point from its neighbours, then replaces them with the checked answers a moment later. Under Advanced you can switch the GPU to the "Exact" tier, which tracks a proven error bound on every step and never paints an estimate, at the cost of speed.
Two engines
One engine runs on your processor in background workers. The other uses the graphics card through WebGPU. Its shading language, WGSL, offers 32-bit and optional 16-bit floats but no 64-bit type, so the GPU path keeps each number as a 32-bit float with a separate wide exponent, rescaled every step, and relies on the glitch test above. An "Exact" tier builds a 72-bit number format from integers and tracks an error bound on every operation; it is the slower audit mode. The explorer's Auto setting uses the graphics card when it passes a start-up check and uses the processor for any single view the card cannot hold. We have only measured this on one machine, so the choice can be changed under Advanced.
Can you zoom forever?
The mathematics puts no floor under the detail. A real explorer meets four practical limits.
- Digits. Deeper views need longer coordinates; the explorer accepts up to 100,000 digits.
- Steps. Views near small copies need big budgets. The menu's 10-318 view uses 212,138; shared links can ask for up to 1,000,000.
- Your device. A view that finishes in a minute on a desktop may not finish on an older phone.
- Where you aim. Zoom into a plain area and there is nothing more to find.
The menu stops at 10-1000 because those are the depths we have tested, not because the set ends there.
What we measured, and what we did not
We timed both engines on the same four 256 × 256 test views in one session on 20 October 2026, on an Apple M4 Mac running Chrome 155, when the GPU engine still used its exact 72-bit arithmetic. The table shows warm runs (caches kept from a first, cold run). Every figure is a single observation, not an average.
| Test view | Iteration budget | Processor | GPU |
|---|---|---|---|
10-113 (e113) | 35,494 | 27.683 s | 20.720 s |
10-318 (e318) | 212,138 | 114.772 s | 91.883 s |
10-1000 (e1000) | 32,000 | 53.132 s | 0.3743 s |
Difficult test view, not in the menu (glitch_test_1) | 275,250 | 73.455 s | 48.162 s |
Apple M4, Chrome 155, 256 × 256 pixels, warm renders, one observation per cell. Elapsed time includes preparation, rendering, presentation and any repair work.
In this session our GPU implementation finished first on all four, but the gap varied hugely: about 20% less time on the 10-318 view, and under 1% of the processor's time on the 10-1000 view, where shortcuts covered almost all the work. Depth alone is a poor guide to render time.
Timings also move between sessions: the same GPU code took 11.490 seconds on the 10-113 view in an earlier session. Treat the table as examples from one machine, not a benchmark.
On 21 October 2026 the GPU engine switched to its fast arithmetic and several other defaults changed; the same machine then rendered the 10-318 view at the explorer's Fast size in 1.2 s (image ready at 0.7 s) instead of about 41 s, the 10-113 view at Fine 800 × 600 in 2.8 s instead of 84 s on the processor, and at the new Ultra 1920 × 1440 size in 9.7 s. The difficult hidden view took 7.5 s at Fast; later changes to how the GPU schedules its work (fewer, longer rounds once only a few pixels are left, and a preview that does not wait for the slowest pixels) brought it to about 3 s, even on a busier machine. The price is that a few percent of pixels in the noisiest regions get a slightly different iteration count than the exact arithmetic would give, which is the trade most deep zoom programs make.
We have not measured phones, Windows machines, other graphics cards, or long sessions of dragging and zooming. Pixels that reach the iteration budget are still counted as unresolved: the difficult view finished with 423 of 65,536 such pixels, now drawn in the dark interior tone. Auto uses the GPU when its start-up check passes and falls back to the processor if needed. You can choose either renderer under Advanced. What we learned testing GPU performance covers the details, including the experiments that did not help.
For developers
Perturbation
Let the reference orbit be Zn for parameter C, and write a pixel's orbit as zn = Zn + δn with parameter c = C + δc. Substituting into zn+1 = zn² + c and cancelling the reference terms leaves:
Only δ is iterated per pixel; Zn comes from the stored orbit, rounded to the working format. Ultra Fractal's perturbation equations page derives this and explains why large terms must cancel before rounding. Claude Heiland-Allen's perturbation notes trace the method back to K. I. Martin's SuperFractalThing.
Rebasing
When |Zn + δn| < |δn|, rebasing sets δ to Zn + δn and restarts at reference index 0, so one reference serves far more pixels and many glitches never happen. Heiland-Allen's Deep Zoom page gives the current equations for rebasing and BLA.
Bivariate linear approximation
When δn² is negligible beside 2Znδn, one step is linear: δn+1 ≈ A δn + B δc with A = 2Zn and B = 1. Composing l steps gives another (A, B) pair, valid while |δ| stays under a radius computed for that block. Munafo's Mu-Ency entry on bivariate linear approximation defines the method. Our tables only allow a skip when escape, cancellation and rebasing are ruled out at both ends of the block.
Extended exponents
The processor kernel keeps significands in doubles and rescales them, with a separate-exponent fallback. The GPU kernel uses the 72-bit integer format above, with error tracking on every operation. Heiland-Allen's Deep zoom theory and practice (2021) discusses exponent limits and rescaling.
Glitch detection and repair
The default GPU tier flags a pixel when |Zm + δ|² falls below 10-4·|Zm|² (Pauldelbrot's criterion) and restarts it in the exact tier, where every pixel carries an error bound and is flagged if the bound grows too wide to decide escape. What the exact tier cannot settle goes to a processor worker using MPFR at reference precision plus 64 bits, with a second run at plus 128 bits whenever the answer lies near a decision boundary. A pixel still undecided when the budget ends is reported as unresolved and drawn as interior. For counters, failed experiments and timing methods, read What we learned testing GPU performance.
Questions people ask
Can you zoom forever?
Not in practice. Deeper views need more digits, steps and time; see the limits above.
Why are some pixels dark or grey?
Dark pixels did not escape within the iteration budget. They might be inside the set or might need more steps; a higher budget resolves some of them. Grey pixels are still being computed.
Why does it take so long?
Pixels near the boundary need many steps. The 256 × 256 render of the 10-113 view involved about 1.5 billion steps, done or skipped. Since October 2026 the GPU engine finishes most views in a few seconds and shows a rough version within a second; the processor engine is still much slower.
Does it work on my phone?
It supports drag and pinch, but we have not yet measured it on physical phones. Start with shallow views; the deepest may be too heavy for some devices.
What do the colours mean?
How quickly each point escaped, through a palette you can change. Only the dark interior tone, grey and pale pink have fixed meanings.
Where to go next
Sources and further reading
- B. B. Mandelbrot, Fractal aspects of the iteration of z → λz(1 − z) for complex λ and z (1980), with a scan hosted at Harvard. Original paper on this quadratic family.
- A. Douady and J. H. Hubbard, Étude dynamique des polynômes complexes. Foundational notes on the parameter plane and Julia sets.
- M. Shishikura, The Hausdorff dimension of the boundary of the Mandelbrot set and Julia sets. Proof that the boundary has dimension 2.
- Linas Vepstas, Renormalizing the Mandelbrot Escape. Derivation of the smooth escape value behind the colouring.
- Mikael Hvidtfeldt Christensen, Double Precision in OpenGL and WebGL. Why graphics shaders hit the precision wall early.
- GNU MPFR manual and gmp-wasm source. The arbitrary precision library used for reference orbits and repairs.
- Phil Thompson, Perturbation Theory and the Mandelbrot set (2022). Readable introduction to perturbation.
- Phil Thompson, Faster Mandelbrot Set Rendering with BLA (2023). How step skipping works in practice.
- Robert Munafo, Mu-Ency: Floatexp. The extended exponent number format.
- Robert Munafo, Mu-Ency: Bivariate Linear Approximation. Definition of BLA.
- Ultra Fractal, Perturbation equations. The perturbation algebra and why large terms must cancel first.
- Claude Heiland-Allen, Mandelbrot set perturbation notes. History of the method, including K. I. Martin's SuperFractalThing.
- Claude Heiland-Allen, Perturbation glitches (2014). What glitches are and how they appear.
- Claude Heiland-Allen, Deep zoom theory and practice (2021). Exponent limits and rescaling.
- Claude Heiland-Allen, Deep Zoom. Current equations for rebasing and BLA.
- W3C, WebGPU Shading Language: floating point types. WGSL has no 64-bit float type.
- Fraktaler 3 and Kalles Fraktaler 2+. Independent deep zoom programs that accept the same coordinates.
- rust-fractal-core test locations. Origin of the deep view coordinates.