2013-04-18 3 views
4

У меня есть код для построения набора mandlebrot с использованием pygame. Вот код.Python 3.2 vs Python 2.7 проблемы с кодом

import pygame, sys, math 
from decimal import * 
window=pygame.display.set_mode((1000, 1000)) 
window.fill((255, 255, 255)) 
pygame.display.update() 
winrect=window.get_rect() 
hq=3 
getcontext().prec=20 
colors=((255, 0, 0), (255, 128, 0), (255, 255, 0), (128, 255, 0), (0, 255, 0), (0, 255, 128), (0, 255, 255), (0, 128, 255), (0, 0, 255), (128, 0, 255), (255, 0, 255), (255, 0, 128)) 
def graph(scale):#left, right, bottom, top 
    window.fill((0, 0, 0)) 
    minimum=-1 
    y=((scale[3]-scale[2]))/(winrect.height)+scale[2] 
    for a in range(winrect.width): 
     x=((scale[1]-scale[0])*(a))/(winrect.width)+scale[0] 
     d, e=x**2-y**2+x, 2*x*y+y 
     for i in range(int(1/(50*(scale[1]-scale[0]))+25)): 
      d, e=d**2-e**2+x, 2*d*e+y 
      if math.sqrt(d**2+e**2)>2: 
       if i<minimum or minimum==-1: 
        minimum=i 
       break 
    y=((scale[3]-scale[2])*winrect.height)/(winrect.height)+scale[2] 
    for a in range(winrect.width): 
     x=((scale[1]-scale[0])*a)/winrect.width+scale[0] 
     d, e=x**2-y**2+x, 2*x*y+y 
     for i in range(int(1/(50*(scale[1]-scale[0]))+25)): 
      d, e=d**2-e**2+x, 2*d*e+y 
      if math.sqrt(d**2+e**2)>2: 
       if i<minimum or minimum==-1: 
        minimum=i 
       break 
    x=((scale[1]-scale[0])*1)/winrect.width+scale[0] 
    for b in range(winrect.height): 
     y=((scale[3]-scale[2])*b)/winrect.height+scale[2] 
     d, e=x**2-y**2+x, 2*x*y+y 
     for i in range(int(1/(50*(scale[1]-scale[0]))+25)): 
      d, e=d**2-e**2+x, 2*d*e+y 
      if math.sqrt(d**2+e**2)>2: 
       if i<minimum or minimum==-1: 
        minimum=i 
       break 
    x=((scale[1]-scale[0])*winrect.width)/winrect.width+scale[0] 
    for b in range(winrect.height): 
     y=((scale[3]-scale[2])*b)/winrect.height+scale[2] 
     d, e=x**2-y**2+x, 2*x*y+y 
     for i in range(int(1/(50*(scale[1]-scale[0]))+25)): 
      d, e=d**2-e**2+x, 2*d*e+y 
      if math.sqrt(d**2+e**2)>2: 
       if i<minimum or minimum==-1: 
        minimum=i 
       break 
    for a in range(winrect.width): 
     for b in range(winrect.height): 
      x=((scale[1]-scale[0])*a)/winrect.width+scale[0] 
      y=((scale[3]-scale[2])*b)/winrect.height+scale[2] 
      d, e=x**2-y**2+x, 2*x*y+y 
      for i in range(minimum): 
       d, e=d**2-e**2+x, 2*d*e+y 
      for i in range(20*hq): 
       d, e=d**2-e**2+x, 2*d*e+y 
       if math.sqrt(d**2+e**2)>2: 
        window.set_at((a, b), colors[i-(int(i/len(colors))*len(colors))]) 
        break 
      for event in pygame.event.get(): 
       if event.type==pygame.QUIT: 
        pygame.quit() 
        sys.exit() 
       if event.type==pygame.KEYDOWN: 
        if event.key==pygame.K_ESCAPE: 
         pygame.quit() 
         sys.exit() 
     pygame.display.update() 
    pygame.display.update() 
graph([-3, 2, -2.5, 2.5, 0])# 
scale=[-3, 2, -2.5, 2.5, 0] 
scalea=scale[:] 
while True: 
    for event in pygame.event.get(): 
     if event.type==pygame.QUIT: 
      pygame.quit() 
      sys.exit() 
     if event.type==pygame.KEYDOWN: 
      if event.key==pygame.K_ESCAPE: 
       pygame.quit() 
       sys.exit() 
      if event.key==pygame.K_r: 
       graph([-3, 2, -2.5, 2.5, 0]) 
       scale=[-3, 2, -2.5, 2.5, 0] 
       scalea=scale[:] 
      if event.key==pygame.K_p: 
       hq+=1 
       graph(scale) 
      if event.key==pygame.K_o: 
       if not hq==1: 
        hq-=1 
        graph(scale) 
      if event.key==pygame.K_SPACE: 
       print(scale) 
       print(scale[1]-scale[0]) 
     if event.type==pygame.MOUSEBUTTONDOWN: 
      if not scalea[4]: 
       scalea[0]=(((scale[1]-scale[0])*event.pos[0])/winrect.width)+scale[0] 
       scalea[2]=(((scale[3]-scale[2])*event.pos[1])/winrect.height)+scale[2] 
       scalea[4]=1 
      else: 
       scalea[1]=(((scale[1]-scale[0])*event.pos[0])/winrect.width)+scale[0] 
       scalea[3]=(((scale[3]-scale[2])*event.pos[1])/winrect.height)+scale[2] 
       scalea[4]=0 
       if scalea[1]<scalea[0]: 
        scalea=[scalea[1], scalea[0], scalea[2], scalea[3], 0] 
       if scalea[3]<scalea[2]: 
        scalea=[scalea[0], scalea[1], scalea[3], scalea[2], 0] 
       scale=scalea[:] 
       if scale[1]-scale[0]<scale[3]-scale[2]: 
        scale[1]+=((scalea[3]-scalea[2])-(scalea[1]-scalea[0]))/2 
        scale[0]-=((scalea[3]-scalea[2])-(scalea[1]-scalea[0]))/2 
       else: 
        scale[2]-=((scalea[1]-scalea[0])-(scalea[3]-scalea[2]))/2 
        scale[3]+=((scalea[1]-scalea[0])-(scalea[3]-scalea[2]))/2 
       graph(scale) 

Когда я запускаю его в python 3.2, он отлично работает. Изображение выглядит следующим образом:

[IMG]http://i47.tinypic.com/2ps0d8n.jpg[/IMG]

Однако, когда я запускаю его в Python 2.7, я получаю ужасное выглядящее изображение, которое выглядит следующим образом:

[IMG]http://i47.tinypic.com/2a0nskk.jpg[/IMG]

Есть ли способ можете это исправить?

+7

Вы говорите только «ужасно», потому что это не то, что вы ожидали. Я думаю, что это выглядит здорово! – Todd

+1

Похож на «BIT.TRIP Mandelbrot» ... ^^ – poke

+0

@Todd Вы должны быть в современном искусстве. – PygameNerd

ответ

10

Да, добавьте это в верхней части файла:

from __future__ import division 

Python 2 использует целочисленное деление (пол деление) при использовании целочисленных входов по умолчанию; Python 3 переключился на деление с плавающей запятой даже при использовании целых входов.

См PEP 238, какие документы изменения:

Оператор ток деление (/) имеет двойственное значение для численных аргументов: она возвращает слово математического результата деления, если аргументы ints или longs, но он возвращает разумную аппроксимацию результата деления, если аргументы являются поплавками или сложными. Это делает выражения ожидающими плавающих или сложных результатов, подверженных ошибкам, когда целые числа не являются ожидаемыми, но возможны в качестве входных данных.

+0

Это сработало отлично, но у меня есть другой вопрос. Даже когда я нахожусь на 3.2, как только я увеличиваю масштаб, я получаю аналогичную картину с прежним 2.7, что, по моему мнению, связано с отсутствием точности в Python. Я использовал десятичный модуль, чтобы попытаться избавиться от него, но он занимает больше времени, когда я это делаю. Любые решения? – PygameNerd

+4

Не совсем; С плавающей точкой действительно есть предел точности, но поскольку они обрабатываются аппаратным обеспечением вашего ПК, они также намного быстрее обрабатываются. Вы можете переключиться на использование [целых чисел для вычисления мандельброта] (http://www.nahee.com/spanky/www/fractint/). Вот так я играл с фракталами 20 с лишним лет назад, во всяком случае, с FRACTINT. :-) –

6

Добавить from __future__ import division наверху.

Смежные вопросы