mandelbrot 集在大约 2^47 缩放时变得模糊

mandelbrot set gets blurry at around 2^47 zoom

所以我创建了一个简单的 mandelbrot 缩放代码,可以在您单击的位置放大 (lmb) 或缩小 (rmb)。每次单击放大曲线时,渲染的部分都会减半。

问题是无论 maxiter 和 additer 计数有多大,分形似乎总是在 2^47 缩放值左右变得模糊。 Here is what it looks like at 2^49 zoom.

下面是我的代码。谁能告诉我为什么它变得模糊以及我该如何解决这个问题?

import numpy as np
from numba import jit
from matplotlib import pyplot as plt
from matplotlib import colors
from datetime import datetime


width, height, resolution = 8, 8, 100
maxiter = 50    #starting maxiter
additer = 50    #value to add to maxiter upon zoom
xmin, xmax = -2, 1
ymin, ymax = -1.5, 1.5
zoom = 1
color = 'terrain'   #https://matplotlib.org/3.1.0/tutorials/colors/colormaps.html


#--------------------------------------------------------------------------------------------------#

@jit
def mandel(c, maxiter):
    z = c
    for n in range(maxiter):
        if (z.real*z.real + z.imag*z.imag)>4:   #if z diverges
            return n
        z = (z * z) + c
    return 0



@jit
def mandelbrot(xmin, xmax, ymin, ymax, maxiter):
    re = np.linspace(xmin, xmax, width*resolution)
    im = np.linspace(ymin, ymax, height*resolution)
    answer = np.empty((width*resolution, height*resolution))
    for y in range(height*resolution):
        for x in range(width*resolution):
            answer[x,y] = mandel(re[x] + 1j*im[y], maxiter) #iteration count at (re, im)
    return answer



def onclick(event):
    global zoom, xmax, xmin, ymax, ymin, maxiter
    if event.button == 1:
        zoom *= 2
        maxiter += additer
    elif event.button == 3:
        zoom/=2
        if maxiter > additer:
            maxiter -= additer
    #get the re,im coordinate position of mouse
    posx = xmin + (xmax-xmin)*event.xdata/(width*resolution)
    posy = ymin + (ymax-ymin)*event.ydata/(height*resolution)
    print(posx, posy, "iter:", maxiter, "zoom:", zoom)
    #change max and min so the coordinate is at the center
    xmin = posx - (1.5/zoom)
    xmax = posx + (1.5/zoom)
    ymin = posy - (1.5/zoom)
    ymax = posy + (1.5/zoom)
    #recalculate and display
    answer = mandelbrot(xmin, xmax, ymin, ymax, maxiter)
    plt.imshow(answer.T, cmap=color)
    plt.draw()

#for benchmarking
'''a = datetime.now()
mandelbrot(xmin, xmax, ymin, ymax, zoom)
print(datetime.now() - a)'''

answer = mandelbrot(xmin, xmax, ymin, ymax, maxiter)
plt.connect('button_press_event', onclick)
plt.imshow(answer.T, cmap=color)
plt.axis('off')
plt.tight_layout()
plt.show()

低于 2^-47 的图像宽度以及您想要缩放的大部分区域,2 个相邻像素之间的差异(考虑 1000 像素宽度)将在标准双精度下产生 0。

要更深入,您需要使用 multi-precision 算术包(十进制,gmpy2)计算至少一个点(参考轨道)。对于剩余的像素,为了使计算时间保持在可接受的范围内,您通常可以仅迭代增量 - 有一些超出此问题范围的警告。

有关使用 python / numpy 实现的示例,您可以查看类似 fractalshades 的包。文档的图库部分包含 Mandelbrot 和 Burning Ship 的 deep-zooms 到 10^-2000 的示例: https://gbillotey.github.io/Fractalshades/examples/index.html

免责声明:我是 fractalshades 的作者。