Mandelbrot集很快就达到了极限

时间:2012-01-31 21:46:06

标签: 3d mandelbrot heightmap

我正在计算mandelbrot设置,能够使用OpenGL将其缩放并打印到屏幕上。

如你所知,mandelbrot set由一个矩形(右上角和左下角)定义,每当我'放大'和'缩小'时,我通过将左下角移动到右上角来改变以下几点侧面和右上角反之亦然。最终这两个点应该相互见面并完成缩放过程 根据许多YOUTUBE电影,我可以清楚地看到一些电影可以让你达到1000倍变焦。在我的节目中,我很难达到X6。在调试时,我可以看到我的2个点,它们定义了mandelbrot集彼此相距(x1,y1) = (x2,y2) 很少的事情:
(x1,y1) & (x2,y2)被定义为浮点数。我应该用双倍代替吗? 我的mandelbrot由(512X512)点定义。够了吗?虽然我不确定它是否与问题有关。

另一个问题我面临的是 - 我将该组打印为高度图(3D集)。当每个Y分量表示迭代量时,它需要一定的点才能达到无穷大。但每次我放大整个设置都会上下移动到我的相机的位置,最终我的相机被设备消耗。有没有办法计算差异并将相机移离设备(相应地从变焦点?)

计算集合的代码:

double ratiox = instance->foundPointOnHost.x / ((instance->constVal[1][0] - instance->constVal[0][0]));;
            double ratioy = 1-instance->foundPointOnHost.z / ((instance->constVal[1][1] - instance->constVal[0][1]));;
            double xrange = instance->m_GraphConfig.xru-instance->m_GraphConfig.xld;
            double yrange = instance->m_GraphConfig.yru-instance->m_GraphConfig.yld;
            instance->m_GraphConfig.xld += 5*direction*0.005*ratiox*xrange;
            instance->m_GraphConfig.xru -= 5*direction*0.005*(1.-ratiox)*xrange;
            instance->m_GraphConfig.yld += 5*direction*0.005*(1.-ratioy)*yrange;
            instance->m_GraphConfig.yru -= 5*direction*0.005*ratioy*yrange;  

一些事情:

instance-> FoundPointOnHost =我要放大的点。
instance-> constVal =包含集合的原始大小(在开头等于[xru,yru] [xld,yld])
(xru,yru)=集合的右上角 (xld,yld)=集合的左下角

谢谢!

2 个答案:

答案 0 :(得分:1)

是的,如果可以,您应该使用double代替float

一个浮点只有24位的尾数,当乘以精度极限的值时,生成的额外位就会丢失。

FWIW,我的WebGL mandelbrot生成器(由于WebGL限制为float)确实管理了大约5000倍的缩放。

答案 1 :(得分:1)

感谢您提供代码! (对于明确问题并包括所有相关信息的问题+1)。

它表明你的变焦理论是正确的。在每一步,xrangeyrange将按常数因子(0.975?)进行缩放,窗口将移向foundPointOnHost,在窗口中保持相同的相对位置({{ 1}}和ratioX)。这绝对是缩放背后的正确理论。但实际上,由于浮点运算的工作方式,你如何实现缩放会快速累积舍入误差。

我的经验法则:

  • 每当你乘以或除以两个浮点数时,你就有可能引入一个错误,其大小是结果的最后一位 ;
  • 但每次添加或减去两个浮点数时,您都有可能引入一个错误,其大小为最后一位最大的操作数

工作的例子。假设您正在放大(0.5,0.3),并且您已经缩放,因此ratioYxrange约为0.001。让我们说你使用浮点数(23位,精确度约为7位小数)。在您的代码中,当您减去两个yrange值以重新计算x时,您将减去两个接近0.5的数字,这意味着xrange中的错误与0.0000001 - 0.5的第七个小数位 - 由于结果大约为0.001,因此xrange仅精确到小数点后四位。然后你缩放,比例,并将xrange添加回窗口的边缘(现在大约为0.00025),这也是大约0.5,因此算术运算也只精确到0.0000001,并且窗口边缘本身与前一次调用不准确。显然,如果你正在使用双打,情况会更好,但同样,你的xrange每次循环都会失去精确度;当你达到x6缩放级别时,也许你已经失去了它。

然后“技巧”是减少加法和减法的数量(目前,你在每个缩放步骤中做6次),并确保你的错误在每次迭代时都不会累积。我建议如下:保持xrangexrange,并在每一步重新计算边缘:( yrangeratioX是不变的,您可能需要找出哪一个是ratioY,哪个是ratio:)

1-ratio

xrange *= 0.975; xld = foundPointOnHost.x - ratioX * xrange; xru = foundPointOnHost.x + (1-ratioX) * xrange; 相同。更好的是,使用一个本身不会在每次乘法累积错误的操作来计算y

xrange