我使用了2个for
循环来检查点是否在集合内,但显然这花费了太多的时间,在图本身上给出的细节较少。我如何优化代码以更快地运行,从而为图添加更多的细节?pygame原点在左上角,所以我手动设置每个点相对于中心的位置。
import math
import pygame
class Point:
def __init__(self, x, y):
self.x = x - 250
self.y = y - 250
class Complex:
def __init__(self, real, imaginary):
self.real = real
self.imaginary = imaginary
def __eq__(self, other):
if self.real == other.real:
if self.imaginary == other.imaginary:
return True
return False
def __abs__(self):
return math.sqrt(self.real ** 2 + self.imaginary ** 2)
def __round__(self, n=None):
return Complex(round(self.real, 4), round(self.imaginary, 4))
def __add__(self, other):
return Complex(self.real + other.real, self.imaginary + other.imaginary)
def __sub__(self, other):
return Complex(self.real - other.real, self.imaginary - other.imaginary)
def __mul__(self, other):
return Complex((self.real * other.real) - (self.imaginary * other.imaginary),
(self.real * other.imaginary) + (self.imaginary * other.real))
def zheta(z, c):
return round((z * z) + c, 3)
def mandelbrotNumber(num):
z0 = Complex(0, 0)
c = num
checkList = [Complex(0, 0)]
for i in range(10):
z = zheta(z0, c)
if abs(z) > 2:
return False
if z in checkList:
return True
checkList.append(z)
z0 = z
return True
def plotPoint(x, y):
color = (0, 0, 0)
position = (x, y)
pygame.draw.circle(screen, color, position, 2)
pygame.init()
screen = pygame.display.set_mode((500, 500))
running = True
startPosX = (0, 250)
endPosX = (500, 250)
startPosY = (250, 0)
endPosY = (250, 500)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill("white")
for i in range(-200, 200):
for j in range(-200, 200):
number = Complex(i / 100, j / 100)
if mandelbrotNumber(number):
plotPoint((number.real*100) + 300, (number.imaginary*100) + 250)
pygame.display.flip()
pygame.quit()
字符串
2条答案
按热度按时间esyap4oy1#
如何优化代码以使其运行得更快
1.使用Python内置的复杂类型。
1.去掉四舍五入,那只是不必要的额外步骤。
1.放弃
checkList
,因为完全相等是不可能的,不值得付出努力。1.与其为每个像素画一个圆,不如在内存中构建一个光栅图像(pygame文档建议称之为
Surface
),在其上设置像素,然后在一个绘制操作中将整个图像绘制到应用程序窗口。x33g5p2x2#
1.优化计算
Python有一个内置的类
complex
,它应该更快,因为它是在C中内部实现的,但我猜你实现这个类是为了练习。算法本身可以自行改进-请参阅@MvG列出的内容,但您可以做更多事情来提高速度-计算数字的平方根是一个相当慢的操作,
x**2 + y**2 > 4
将与sqrt(x**2 + y**2) > 2
一样好,但会避免不必要的平方根。有更多的优化,让减少乘法的数量(比sqrt()
的操作成本低,但仍然需要一点)。Wikipedia文章有一节专门介绍优化mandelbrot集绘制算法,请参阅此。太慢了?有一些高级库可以帮助加速操作,
numpy
允许您“一次”对多个值进行操作,但在这里它不是很有用(没有简单的方法可以避免对已经转义的点进行不必要的操作)。更有用的库是numba
-它是python子集的jit编译器,它让你编写代码的速度与编译语言相当。如果你真的想给予一切来提高速度,那么应该使用第三方库来提高性能,但这绝对不是一个初学者友好的解决方案。
2.优化绘图
画圆-这是一个复杂的操作,最好使用类似
surface.set_at()
的东西来设置所选像素的颜色。计算Mandelbrot分形每帧不是一个好主意,你可以有一个单独的表面,你可以画一次Mandelbrot集(当你在屏幕上画,你真的只是画在表面上是链接到窗口,你可以想象表面是一些虚拟的窗口,你看不见,但你可以在他们身上画,就像你通常在窗口上做的那样)
如果你真的想使用
numba
,使用任何与pygame表面相关的函数在numba
will reduce the speed gained for usingnumba
, to avoid this, edit values from an object received from` pygame.surfarray``优化的函数中绘制它们。3.限制
总有一些限制,我上面列出的命题(即使没有关于使用
numba
的命题),你应该得到一个体面的程序来绘制mandelbrot集,但事实是,如果你缩放越来越多,计算所选点是否可能属于mandelbrot集就变得越来越繁重。还有一个问题是你想花多少时间来优化这段代码。