我尝试使用真实值进行重力模拟,但是当我尝试将真实值放入时,我会收到一条错误,上面写着" OverflowError:Python int太大而无法转换为C长"
这些数值与太阳质量(1.98e + 30 kg)一样大 - 我认为这并不是那么大(我希望今年晚些时候用Python进行黑洞模拟)。我试图在Python 2.7和Python 3.4上运行代码,但遗憾的是没有用。
我已经做了一些搜索我发现大多数人在使用大xrange的方法时都会遇到这个错误,事实并非如此(我使用的唯一xrange是最大荣耀0到1)和程序适用于少量质量。
我能做些什么吗?或者Python无法处理这些值(我觉得这不太可能)?
整个Traceback是这样的:
Traceback (most recent call last):
File "Orbit2.py", line 166, in <module>
main()
File "Orbit2.py", line 155, in main
pygame.draw.circle(win, (255, 255, 255), (int(WIDTHD2+zoom*WIDTHD2*(p._est._x-WIDTHD2)/WIDTHD2),int(HEIGHTD2+zoom*HEIGHTD2*(p._est._y-HEIGHTD2)/HEIGHTD2)),int(p._r*zoom), 0)
OverflowError: Python int too large to convert to C long
如果它有助于整个代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import pygame
import math
from collections import defaultdict
# Tamanho da janela
WIDTH, HEIGHT = 900, 600
WIDTHD2, HEIGHTD2 = WIDTH/2., HEIGHT/2.
# Número de planetas
PLANETAS=1
# Constante gravitacional
GRAVCONST = 6.67384e-11
# Densidade média dos planetas
DENSIDADE = 0.001
# Lista global de planetas
g_listaDePlanetas = []
class Estado:
""" Classe que representa a posição e velocidade. """
def __init__(self, x, y, vx, vy):
self._x, self._y, self._vx, self._vy = x, y, vx, vy
def __repr__(self):
return 'x:{x} y:{y} vx:{vx} vy:{vy}'.format(x=self._x, y=self._y, vx=self._vx, vy=self._vy)
class Derivada:
""" Classe que representa a velocidade e aceleração. """
def __init__(self, dx, dy, dvx, dvy):
self._dx, self._dy, self._dvx, self._dvy = dx, dy, dvx, dvy
def __repr__(self):
return 'dx:{dx} dy:{dy} dvx:{dvx} dvy:{dvy}'.format(dx=self._dx, dy=self._dy, dvx=self._dvx, dvy=self._dvy)
class Planeta:
""" Classe que representa um planeta. A parte "_est" significa "Estado", que carrega
a posição e a velocidade do planeta. Enquanto "_m" representa a massa."""
def __init__(self):
self._est = Estado (150, 300, 0, 2)
self._r = 1.5
self._m = 5.97e24
def __repr__(self):
return repr(self._est)
def aceleracao(self, estado, un_t):
""" Calcula a aceleração causada por outro planeta neste."""
ax = 0.0
ay = 0.0
for p in g_listaDePlanetas:
if p is self:
continue
dx = p._est._x - estado._x
dy = p._est._y - estado._y
dsq = dx*dx + dy*dy # distância quadratica
dr = math.sqrt(dsq) # distância
forca = GRAVCONST*self._m*p._m/dsq
ax += forca*dx/dr
ay += forca*dy/dr
return (ax, ay)
def iniDerivada(self, estado, t):
""" Parte do método de Runge-Kutta. """
ax, ay = self.aceleracao(estado, t)
return Derivada(estado._vx, estado._vy, ax, ay)
def proxDerivada(self, iniEstado, derivada, t, dt):
""" Parte do método de Runge-Kutta. """
estado = Estado(0.0, 0.0, 0.0, 0.0)
estado._x = iniEstado._x + derivada._dx*dt
estado._y = iniEstado._y + derivada._dy*dt
estado._vx = iniEstado._vx + derivada._dvx*dt
estado._vy = iniEstado._vy + derivada._dvy*dt
ax, ay = self.aceleracao(estado, t+dt)
return Derivada(estado._vx, estado._vy, ax, ay)
def atualizarPlaneta(self, t, dt):
""" Solução de Runge-Kutta de quarta ordem para pos/vel do planeta. """
k1 = self.iniDerivada(self._est, t)
k2 = self.proxDerivada(self._est, k1, t, dt*0.5)
k3 = self.proxDerivada(self._est, k2, t, dt*0.5)
k4 = self.proxDerivada(self._est, k3, t, dt)
dxdt = 1.0/6.0 * (k1._dx + 2.0*(k2._dx + k3._dx) + k4._dx)
dydt = 1.0/6.0 * (k1._dy + 2.0*(k2._dy + k3._dy) + k4._dy)
dvxdt = 1.0/6.0 * (k1._dvx + 2.0*(k2._dvx + k3._dvx) + k4._dvx)
dvydt = 1.0/6.0 * (k1._dvy + 2.0*(k2._dvy + k3._dvy) + k4._dvy)
self._est._x += dxdt*dt
self._est._y += dydt*dt
self._est._vx += dvxdt*dt
self._est._vy += dvydt*dt
def massaFromRaio(self):
""" A partir de _r define _m. """
self._m = DENSIDADE*4.*math.pi*(self._r**3.)/3.
def raioFromMassa(self):
""" A partir de _m define _r. """
self._r = (3.*self._m/(DENSIDADE*4.*math.pi))**(0.3333)
def main():
pygame.init()
win=pygame.display.set_mode((WIDTH, HEIGHT))
keysPressed = defaultdict(bool)
def ScanKeyboard():
while True:
evt = pygame.event.poll()
if evt.type == pygame.NOEVENT:
break
elif evt.type in [pygame.KEYDOWN, pygame.KEYUP]:
keysPressed[evt.key] = evt.type == pygame.KEYDOWN
global g_listaDePlanetas, PLANETAS
g_listaDePlanetas = []
for i in xrange(0, PLANETAS):
g_listaDePlanetas.append(Planeta())
sol = Planeta()
# Centraliza o sol na tela
sol._est._x, sol._est._y = WIDTHD2, HEIGHTD2
sol._est._vx = sol._est._vy = 0.0
sol._m = 1.989e30 # Massa do sol
sol._r = 3.5
#sol.raioFromMassa()
g_listaDePlanetas.append(sol)
t, dt = 0.0, 1.0
zoom = 1.0
bClearScreen = True
pygame.display.set_caption("Simulador de órbitas RK-4")
while True:
t += dt
pygame.display.flip()
if bClearScreen: # Mostrar orbitas ou não
win.fill((0, 0, 0))
win.lock()
for p in g_listaDePlanetas:
pygame.draw.circle(win, (255, 255, 255), (int(WIDTHD2+zoom*WIDTHD2*(p._est._x-WIDTHD2)/WIDTHD2),int(HEIGHTD2+zoom*HEIGHTD2*(p._est._y-HEIGHTD2)/HEIGHTD2)),int(p._r*zoom), 0)
win.unlock()
ScanKeyboard()
for p in g_listaDePlanetas:
p.atualizarPlaneta(t, dt)
if keysPressed[pygame.K_ESCAPE]:
break
if __name__ == "__main__":
main()
答案 0 :(得分:0)
首先,您需要了解不同类型的合法值范围。 largest int on most system is 9.2e18。6.2.6.2p2。在大多数代码中,您使用的是浮点数,因此这不是问题。但是,你可以在你发布的堆栈跟踪中看到你遇到了麻烦:
pygame.draw.circle(win, (255, 255, 255), (int(WIDTHD2+zoom*WIDTHD2*(p._est._x-WIDTHD2)/WIDTHD2),int(HEIGHTD2+zoom*HEIGHTD2*(p._est._y-HEIGHTD2)/HEIGHTD2)),int(p._r*zoom), 0)
我没有跟踪你发布的所有代码,以确定在那里计算的是什么或为什么,但是可以说,对int()
的两个调用中的一个是计算一些非常大的值并且试图将它转换为int,这是行不通的。我猜测如果你画圈子,这不是你代码的核心部分(但是我再没有跟踪代码或试着将评论翻译成英文) - 我猜这只是为了可视化。如果是这样,我建议将这些缩小到更小,更小。如果你缩放所有内容,它在屏幕上应该看起来一样,但你可以在你需要的地方使用整数数学。