我已经看过其他有关此事的问题,但我似乎无法弄清楚我哪里出错了。目标是“编写一个程序,通过对跨越-2≤x≤2和-2≤y的区域的N×N网格执行c = x + iy的所有值的迭代来制作Mandelbrot集的图像≤2。制作一个密度图,其中Mandelbrot集内的网格点为黑色,外部的网格点为白色。如果在Mandelbrot集合中,则当z'= z ^ 2 + c迭代时,z的大小永远不会大于2。
我的代码生成的网格几乎全黑,只有一小块白色。
from pylab import imshow,show,gray
from numpy import zeros,linspace
z = 0 + 0j
n=100
M = zeros([n,n],int)
xvalues = linspace(-2,2,n)
yvalues = linspace(-2,2,n)
for x in xvalues:
for y in yvalues:
c = complex(x,y)
for i in range(100):
z = z*z + c
if abs(z) > 2.0:
M[y,x] = 1
break
imshow(M,origin="lower")
gray()
show()
对于任何未来的读者,以下是我的新代码最终的结果:
from pylab import imshow,show,gray
from numpy import zeros,linspace
n=1000
M = zeros([n,n],int)
xvalues = linspace(-2,2,n)
yvalues = linspace(-2,2,n)
for u,x in enumerate(xvalues):
for v,y in enumerate(yvalues):
z = 0 + 0j
c = complex(x,y)
for i in range(100):
z = z*z + c
if abs(z) > 2.0:
M[v,u] = 1
break
imshow(M,origin="lower")
gray()
show()
答案 0 :(得分:2)
您的代码存在一些问题。
首先,您使用xvalues
和yvalues
来索引M
,但这些索引应该是0 ..(n-1)范围内的像素索引整数。 Numpy会将xvalues
和yvalues
中的浮点数转换为整数,但结果数字将在-2..2中,因此不会绘制很多像素,图像会很小由于负索引在Python中的工作方式,你会得到包装。
获取所需像素索引的一种简单方法是使用内置的Python函数enumerate
,但是可能有一种方法可以使用Numpy函数重新组织代码来执行此操作。
另一个问题是您需要为每个像素将z
重置为零。目前,您的代码重复使用前一个像素的最后z
,如果该像素位于Mandelbrot集中,那么z
将会过大。
这是修复后的代码版本。我没有pylab,所以我用PIL编写了一个简单的位图查看器。您可以通过调用img.save(filename)
函数中的show
将图像保存到文件中; PIL将从文件扩展名中找出正确的文件格式。
import numpy as np
from PIL import Image
def show(data):
img = Image.frombytes('1', data.shape[::-1], np.packbits(data, 1))
img.show()
n = 100
maxiter = 100
M = np.zeros([n, n], np.uint8)
xvalues = np.linspace(-2, 2, n)
yvalues = np.linspace(-2, 2, n)
for u, x in enumerate(xvalues):
for v, y in enumerate(yvalues):
z = 0
c = complex(x, y)
for i in range(maxiter):
z = z*z + c
if abs(z) > 2.0:
M[v, u] = 1
break
show(M)
这是输出图像:
当然,每当你发现自己在迭代Numpy数组索引时,这就表明你做错了。使用Numpy的要点是它可以通过在C速度内部迭代它们来同时对整个数组执行操作;上面的代码也可能使用普通的Python列表而不是Numpy数组。
这是一个让Numpy完成大部分循环的版本。它使用了更多的RAM,但它比以前的版本快了大约2.5倍,并且它有点短。
此代码使用多个2D数组。 c
包含所有复杂的种子数,我们在z
中执行核心Mandelbrot计算,该计算初始化为零。 mask
是一个布尔数组,用于控制需要执行Mandelbrot计算的位置。其所有项目最初都设置为True
,并且在每次迭代True
中mask
中与z
中与Mandelbrot集合中转义的项目对应的项目设置为{ {1}}。
要测试某个点是否已转义,我们使用False
而非z.real**2 + z.imag**2 > 4.0
,这会节省一点时间,因为它可以避免昂贵的平方根计算和abs(z) > 2.0
函数调用。
我们可以使用abs
的最终值来绘制Mandelbrot集合,但为了使Mandelbrot中的点设置为黑色,我们需要反转其值,我们可以使用mask
。< / p>
1 - mask
答案 1 :(得分:-1)
from pylab import imshow,show,gray
from numpy import zeros,linspace
N=1000
A=zeros([N+1,N+1],float)
def mandler(x,y):
c=complex(x,y)
z=c
n=0
while n<N:
z=z*z+c
if abs(z)>2:
return 0
n+=1
else:
return 1
for x in linspace(-2,2,N):
for y in linspace(2,-2,N):
a=mandler(x,y)
s=int(((x+2)*N)/4)
t=int(((y+2)*N)/4)
A[s,t]=a
imshow(A)
gray()
show()