改进我的 Mandelbrot 集代码

Posted

技术标签:

【中文标题】改进我的 Mandelbrot 集代码【英文标题】:Improvement to my Mandelbrot set code 【发布时间】:2013-04-13 23:57:36 【问题描述】:

我在 C 语言中有以下 Mandelbrot 集代码。我正在计算并为最终的分形图像创建一个 .ppm 文件。关键是我的分形图像是颠倒的,这意味着它旋转了 90 度。您可以通过执行我的代码来检查它: ./mandel > test.ppm

另一方面,我也想改变颜色。我想实现这个分形图像:

我的最后一个问题是我的代码没有检查我的代码的运行时间。我也有这部分的代码,但是当代码执行完成时,它不会打印运行时间。如果有人可以对我的代码进行适当的更改并帮助我实现这个分形图像,并显示经过的时间,我会很高兴。

#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

void color(int red, int green, int blue)

    fputc((char)red, stdout);
    fputc((char)green, stdout);
    fputc((char)blue, stdout);


int main(int argc, char *argv[])

    int w = 600, h = 400, x, y; 
    //each iteration, it calculates: newz = oldz*oldz + p, where p is the current pixel, and oldz stars at the origin
    double pr, pi;                   //real and imaginary part of the pixel p
    double newRe, newIm, oldRe, oldIm;   //real and imaginary parts of new and old z
    double zoom = 1, moveX = -0.5, moveY = 0; //you can change these to zoom and change position
    int maxIterations = 1000;//after how much iterations the function should stop

    clock_t begin, end;
    double time_spent;

    printf("P6\n# CREATOR: E.T / mandel program\n");
    printf("%d %d\n255\n",w,h);

    begin = clock();

    //loop through every pixel
    for(x = 0; x < w; x++) 
    for(y = 0; y < h; y++)
    
        //calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
    pr = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
        pi = (y - h / 2) / (0.5 * zoom * h) + moveY;
        newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
        //"i" will represent the number of iterations
        int i;
        //start the iteration process
        for(i = 0; i < maxIterations; i++)
        
            //remember value of previous iteration
            oldRe = newRe;
            oldIm = newIm;
            //the actual iteration, the real and imaginary part are calculated
            newRe = oldRe * oldRe - oldIm * oldIm + pr;
            newIm = 2 * oldRe * oldIm + pi;
            //if the point is outside the circle with radius 2: stop
            if((newRe * newRe + newIm * newIm) > 4) break;
        

        color(i % 256, 255, 255 * (i < maxIterations));

    

    end = clock();

    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("Elapsed time: %.2lf seconds.\n", time_spent);

    return 0;

【问题讨论】:

【参考方案1】:

第 1 部分: 您需要将循环的顺序交换为:

for(y = 0; y < h; y++)
for(x = 0; x < w; x++)

这将为您提供正确方向的分形。

第 2 部分: 为了有时间打印出来,您应该将其打印到 stderr,因为您正在将 ppm 输出打印到 stdout:

fprintf(stderr, "Elapsed time: %.2lf seconds.\n", time_spent);

第 3 部分: 要获得连续平滑的着色,您需要使用 Normalized Iteration Count 方法或类似方法。这是您的着色部分的替代品,可为您提供与您想要的相似的东西:

    if(i == maxIterations)
        color(0, 0, 0); // black
    else
    
        double z = sqrt(newRe * newRe + newIm * newIm);
        int brightness = 256. * log2(1.75 + i - log2(log2(z))) / log2(double(maxIterations));
        color(brightness, brightness, 255);
    

它并不完全存在,因为我对标准化迭代计数方法做了一个简单的近似实现。

这不是一个完全连续的着色,但它有点接近。

【讨论】:

谢谢!它解决了我的问题。但是在代码的最后一部分中存在一个关于括号的小错误。如果你能为了其他人而纠正它,那就太好了。 @erkant,你的意思是双倍(maxIterations)吗?使用 gcc 对我来说效果很好。是别的吗? 是的,我在谈论它。它对我不起作用,我不得不使用像 ((double)maxIterations) 这样的括号。 好吧,也许我使用的编译器比你更新/不同。我通常用 C++ 编写代码,所以也许这在 C 中并不有效。

以上是关于改进我的 Mandelbrot 集代码的主要内容,如果未能解决你的问题,请参考以下文章

将颜色层添加到 mandelbrot 集

让 C# mandelbrot 绘图更高效

找不到按照我的目标为 Mandelbrot 上色的方法

Mandelbrot 集函数未按预期执行

sql 在SQL中绘制Mandelbrot集

当分辨率高于 320 像素时,Mandelbrot 代码不令人兴奋? [复制]