Search code examples
pythonpython-3.xmathcolorsmandelbrot

What's wrong with my maths in my attempt to draw the Mandelbrot set?


I am currently trying to code a programm in python which result in drawing the mandelbrot set. The shape of the fractal looks ok but the outline isn't precise at all. I am trying to figuring if the problem comes from my maths or my code

I tried to raise the max number of iterations (which I called i) to see if the calculation was just too low but it didn't change much.

import numpy as np
from PIL import Image

taille = 1000
nb_points = 500
centre_x = taille/2
centre_y = taille/2

fractale = np.zeros((taille, taille, 3), dtype = np.uint8)

for x in range(-nb_points,nb_points):
    x = float(x)
    x = x/250

    for y in range(-nb_points,nb_points):
        y = float(y)
        y = y/250

        X = float(0)
        Y = float(0)
        i = 0

        module_carre = 0

        while module_carre < 4 and i <20 :
            X = float(X**2 - Y**2 + x)
            Y = float(2*X*Y + y)
            i += 1 
            module_carre = float(X*X + Y*Y)

        if module_carre < 4:
            i=0

        couleur = liste_couleur[i]

        fractale[centre_x + x*250,centre_y + y*250] = couleur
imgpil = Image.fromarray(fractale, 'RGB')
imgpil.save("resultat.jpg")

I am French that's why you might not understand everything. I didn't paste all the lines about defining differents shades of blue etc... I don't understand why my outline is this bad. I believe that it comes from my maths but i don't see any errors. It's my first time posting on stack overflow and i don't understand evey tools yet. I didn't manage to add the image of the output Sorry for my English and I hope you'll be able to help me fix my code


Solution

  • The main problem is here:

    X = float(X**2 - Y**2 + x)
    Y = float(2*X*Y + y)
    

    In the calculation for Y, you want to use the old value of X, but it's already been updated and is no longer available. You could instead do:

    new_X = float(X**2 - Y**2 + x)
    Y = float(2*X*Y + y)
    X = new_X
    

    Or you could update them in parallel:

    X, Y = float(X**2 - Y**2 + x), float(2*X*Y + y)
    

    Also, you don't need the calls to float, so all you really need is:

    X, Y = X**2 - Y**2 + x, 2*X*Y + y
    

    By the way, Python does have a built-in complex number class, so you could initialize z and Z as z = complex(x, y) and Z = complex(0.0, 0.0). Then your loop body would have:

    Z = Z**2 + z
    

    I also suggest increasing the maximum number of iterations. Limiting it to 20 will give very low resolution. I usually use at least 1000, at least for points near the boundary, when generating high-res images.