2014-02-25 27 views
2

我想写一个程序,它使用递归来解决直接射入空中的对象的速度,并计算它在击中地面时计算重力随高度变化用这个方程g(s) = G∙ME/(RE + s)^2位移与这个方程s(t) = s(t-∆t) + v(t)∙∆t和速度与这个方程v(t) = v(t-∆t) - g(s(t-∆t)) ∙ ∆t我使用前面的值(表示为t-Δt)作为输入,然后更新变量并返回它们,这对我来说是有意义的,但我必须做一些事情错误。最初我得到一个错误,说最大递归限制被超过,但在一些谷歌搜索后,我发现我应该改变递归限制。现在程序看起来像是开始运行,但在输出任何东西之前python崩溃。我一直无法弄清楚我能做些什么来完成这项工作。任何帮助将不胜感激python中的递归,python每次运行时崩溃

import math as m 
import sys 
sys.setrecursionlimit(20000) 
    # 
    # 
    # Method that runs the simulation 
    # 

def run(deltat, G, ME, RE, velocity): 
    # set initial time to 0 
    s = 0 
    t = 0 

    # Save the initial velocity because it is needed to find when the ground is hit 
    initialvelocity = velocity 
    # while the height is greater than 0 execute the loop 
    while s >= 0: 
     # Find the height based on gravity, and velocity 
     s = calculatedisplacement(t ,deltat, velocity, s, G, ME, RE) 

     # Calculate the velocity based on the changing gravity 
     velocity = calculatevelocity(velocity, t ,deltat, s, G, ME, RE) 

     # If s is larger than 0 print where the object is 
     if s >= 0: 
      print ("At time t = " + str(t) + " The object is " + str(s) + " meters high") 
      t = t + deltat 
      print("Time: " + str(t)) 

     elif s < 0: 
      print ("The object hits the ground at t = " + str(quadraticsolver((-0.5 * (G * ME))/(m.pow(RE, 2)), initialvelocity, 0))) 


# Function used to calculate gravity 
def calculategravity(s, G, ME, RE): 


    gravity = ((G * ME)/(m.pow((RE + s), 2))) 

    print ("Gravity = " + str(gravity)) 

    return gravity 

# Function used to calculate height 
def calculatedisplacement(t ,deltat, velocity, s, G, ME, RE): 
    s = s + (calculatevelocity(velocity, t ,deltat, s, G, ME, RE) * deltat) 
    print("height = " + str(s)) 
    return s 

# Function used to calculatevelocity 
def calculatevelocity(t ,deltat, velocity, s, G, ME, RE): 
    velocity = velocity - ((calculategravity(G, ME, RE,calculatedisplacement(t ,deltat, velocity, s, G, ME, RE)))* deltat) 
    print("Velocity " + str(velocity)) 
    return velocity 

# Used to solve quadratic equations and find where the object hits the ground 
def quadraticsolver(a, b, c): 
    discriminant = (m.pow(b, 2)) - (2 * a * c) 
    # Two solutions to account for the + or - in the quadratic formula 
    solution1 = (((-b) + (m.sqrt(discriminant)))/(2 * a)) 
    solution2 = (((-b) - (m.sqrt(discriminant)))/(2 * a)) 
    # One solution will always be 0 because height is 0 when time is 0 so return the solution that is not zero 
    # This is the time when height = 0 
    if solution1 == 0: 
     return solution2 
    elif solution2 == 0: 
     return solution1 
+0

你得到了什么错误? – AlG

+3

你实际上并没有显示任何失败的信息,或者对你的任何代码进行调用。请发布回溯(随意删除大约19,980个重复的堆栈帧)。不知道你是如何调用你的函数,很难知道可能会出错。您可能还会看到时间增量的较大值是否会减少呼叫的数量以使您处于界限内。 但是,我怀疑它可以,因为'calculate_velocity'的第一件事就是调用'calculate_displacement',反之亦然,因此当你的逻辑结构化时,几乎没有希望终止这个无限递归。 – holdenweb

回答

4

(这有太大的评论。)

递归是很好的解决很多问题,但迭代数值模拟是不是其中之一。堆栈帧的数量是有限的数量,要谨慎使用(Python对堆栈帧的数量有限制,因为当使用太多时,通常是错误的)。您可能会耗尽为堆栈分配的内存(而不是堆),否则您可能会耗尽所有内存,堆栈和堆。内存不足错误有时不会发出警告,因为程序或操作系统没有资源来生成警告。

如果您将程序改写为forwhile循环,您可能会发现程序更高效,更易于调试,甚至可能无缺陷。

一些编程语言,如计划,鼓励重复使用递归的,但是这些语言在内部转换您的递归函数为while环(“尾调用优化”)。 Python不是这些语言之一:每次调用函数时,它都会创建一个新的堆栈框架,并且不会删除旧的堆栈框架,直到递归结束,这实际上就像是内存泄漏。 (也就是说,对象不再有用,但它们仍然被引用并仍在内存中。)