Exercice : Fractale de Mandelbrot#
La fractale de Mandelbrot est un ensemble de points du plan complexe défini ainsi: soit \(c\) un complexe, on lui associe la suite \((z_n)\) donnée par \(z_0 = 0\) et \(z_{n+1} = z_n^2 + c\). Le complexe \(c\) est dans la fractale ssi la suite \((z_n)\) est bornée.
Le type Complexe, la fonction initComplexe, la fonction egaleComplexe, la
fonction ajouterComplexe et la fonction moduleComplexe vous sont données
ci-dessous. Lisez leur code pour bien les comprendre.
struct Complexe {
    float re, im;
};
void initComplexe(Complexe *c, float reel, float imaginaire) {
    c->re = reel;
    c->im = imaginaire;
}
bool egaleComplexe(Complexe a, Complexe b) {
    return (a.re == b.re) && (a.im == b.im);
}
void ajouterComplexe(Complexe *a, Complexe b) {
    a->re = a->re + b.re;
    a->im = a->im + b.im;
}
float moduleComplexe(Complexe c) {
    return sqrt(pow(c.re, 2) + pow(c.im, 2));
}
- Écrire la fonction - void multiplierComplexesur le modèle de la fonction- ajouterComplexequi prend en entrée deux complexes dont le premier sous la forme d’un pointeur et qui renvoie leur produit en modifiant le premier paramètre.- Faites très attention à la formule : \((a_1+i\,b_1)*(a_2+i\,b_2)= a_1 *a_2 - b_1 * b_2 + i\,(a_1*b_2 + a_2 * b_1)\). En effet, comme en programmation modulaire, la moindre erreur risque de vous faire perdre beaucoup de temps. De plus pensez à bien tester votre fonction. - BEGIN SOLUTION - Attention ici, il ne faut pas modifier le contenu de {\tt a} immédiatement lors du calcul de la partie réelle car on en a besoin pour le calcul de la partie imaginaire. - void multiplierComplexe(Complexe *a, Complexe b){ float re, im; re = a->re * b.re - a->im * b.im; im = a->im * b.re + a->re * b.im; a->re = re; a->im = im; } - END SOLUTION 
- Écrire une fonction booléenne - znResteBornequi prend un complexe \(c\), et renvoie vrai si la suite \(z_n\) associée ne tend pas vers l’infini, faux sinon. On calculera la suite des termes \(z_n\), jusqu’à ce que le module de \(z_n\) devienne plus grand que \(2\) (auquel cas on dira que la suite tend vers l’infini), ou \(1000\) itérations ont été faites (auquel cas on dira que la suite reste bornée).- BEGIN SOLUTION - bool znResteBorne(Complexe c){ Complexe z; initComplexe(&z, 0, 0); for(int i = 0; i < 1000; i++){ if (moduleComplexe(z) > 2){ return false; } multiplierComplexe(&z, z); ajouterComplexe(&z, c); } return true; } - END SOLUTION 
- La procédure - mandelbrotqui vous est donnée ci-dessous utilise la fonction- znResteBorneque vous venez d’écrire pour afficher l’ensemble de Mandelbrot. Elle fait varier \(x\) entre \(-2\) et \(0.5\) et \(y\) entre \(-1.1\) et \(+1.1\), et fait un affichage ASCII sur \(80\times40\) caractères.- void mandelbrot() { const float xmin = -2; const float xmax = 0.5; const float ymin = -1.1; const float ymax = 1.1; const int xresol = 79; const int yresol = 39; for (int i = 0; i <= yresol; i++) { for (int j = 0; j <= xresol; j++) { Complexe z; initComplexe(&z, (xresol - j) * xmin / xresol + j * xmax / xresol, (yresol - i) * ymax / yresol + i * ymin / yresol); if (znResteBorne(z)) { cout << '#'; } else { cout << ' '; } } cout << endl; } } - Exécuter - mandelbrot, puis modifiez cette procédure pour zoomer sur la figure, en faisant varier x et y sur de plus petits intervalles, autour de points pas trop loin de la frontière.