2014-03-05 159 views
1

好的,我已经使用递归函数做了一个函数,如下所示。递归函数帮助(Python)

global totalExposure 
totalExposure = 0 

def f(x): 
    import math 
    return 10 * math.e**(math.log(0.5)/5.27 * x) 

def radiationExposure(start, stop, step): 

    time = (stop-start) 
    newStart = start+step 

    if(time!=0): 
     radiationExposure(newStart, stop, step) 
     global totalExposure 
     radiation = f(start) * step 
     totalExposure += radiation 
     return totalExposure 
    else: 
     return totalExposure 

现在,当我把整数的值,函数工作正常。

rad = radiationExposure(0, 5, 1) 
# rad = 39.1031878433 

然而,我的函数给出了错误的值,当我把在小数的值。 那么,如何让我的函数以小数位工作呢?

例如:

rad = radiationExposure(0, 4, 0.25) 

你的输出: 1217.5725783047335 正确的输出: 1148.6783342153556

+0

您对输出的期望是什么?输出有什么问题? – thefourtheye

+0

只是一个提示,你应该把你的'import'放在开头,这样它不会在每次函数运行时被调用... –

+0

@ aj8uppal无论执行语句的次数多少,实际只会导入一次。 Python不会重新导入已导入的模块。 –

回答

0

我倒是原先回答,这是floordiv的错,那么我认为这是浮点捏造,现在我认为这只是糟糕的代码。让我们看看更深一点,我们会吗?

首先,如果你看到global在你的代码,非常努力地摆脱它。它会一直造成像这样的错误代码。让我们把它改写没有global ....

import math 

def f(x): 
    return 10 * math.e**(math.log(0.5)/5.27 * x) 

def radiationExposure(start, stop, step): 
    totalExposure = 0 
    while stop-start > 0: 
     totalExposure += f(start)*step # I dont' know this formula, but this 
             # feels wrong -- maybe double check the 
             # math here? 
     start += step 
    return totalExposure 

这实际上设法摆脱递归太大,这将节省内存吨。

### DEMO ### 
>>> radiationExposure(0,5,1) 
39.10318784326239 
>>> radiationExposure(0,4,0.25) 
31.61803641252657 

,我看到它是你的global被保存递归之间之间的函数调用的问题。当我第一次运行你的代码时,我得到了:

>>> radiationExposure(0,5,1) 
39.10318784326239 
>>> radiationExposure(0,5,1) 
78.20637568652478 

这显然是错误的。更不用说递归公式应该自称,但他们倾向于在return声明中这样做!写这个递归会是这样的:

def radiationExposure(start, stop, step): 
    time = stop-start 
    new_start = start+step 
    radiation = f(start)*step 
    if time <= 0: # <= accounts for something like (0, 3, 0.33) where it will never EXACTLY hit zero 
     return radiation 
     # if we're on the last tick, return one dose of radiation 
    else: 
     return radiation + radiationExposure(newStart,stop,step) 
     # otherwise, return one dose of radiation plus all following doses 
+0

这是微分方程积分的欧拉方法,这里只是函数f(x)或(平凡)微分方程y'(x)= f(x)的积分。应该补偿'如果时间<= 0:时间可能基本上低于零的情况,所以在这种情况下应该返回'f(start)* time'而不是'f(start)* step'。然后可以将条件改为'if time <= step:',这样最后一个积分步骤准确地落在'stop'处,不会出现超调和反向。 – LutzL

0

首先修正欧拉积分这是保证从开始真正融入到停止,并在停止小量增加一个额外的集成点(大小步骤,改变方法如果浮点错误总结为这种情况,则积分间隔在停止+步骤结束)。

回想一下,差分方程y的欧拉积分'(X)= F(X,Y(X)),Y(X0)= Y0通过反复计算

y=y+h*f(x,y) 
x=x+h 

在纯集成问题进行存在来自于F无Y,积分F(X),从而至b将初始化y = 0的和重复应用

y=y+h*f(x) 
x=x+h 

只要x是小于b。在最后一步中,当b-h < = x < = b时,设置h = b-x,以便积分过程以(浮点)精确地x = b结束。

import math 

def f(x): 
    return 10 * math.exp(math.log(0.5)/5.27 * x) 

def radiationExposure(start, stop, step): 
    totalExposure = 0 
    while stop-start > 0: 
     if stop-start < step: 
      step = stop-start; 

     totalExposure += f(start)*step 

     start += step 
    return totalExposure 

if __name__ == "__main__": 
    print radiationExposure(0,5,1); 
    print radiationExposure(0,5,0.25); 
    print radiationExposure(0,5,0.1); 
    print radiationExposure(0,5,0.01); 

一个更好的解决办法是使用numpy的的数值积分程序。


甚至更​​好,使用此函数f的积分(X)= C * EXP(A * X)经由防导数F实际上已知的(X)= C/A * EXP( C * A),以使得该值R(启动,停止)= F(停止)-F(开始),所以

​​

返回的值是为欧拉积分

39.1031878433 (step=1) 
37.2464645611 (step=0.25) 
36.8822478677 (step=0.1) 
36.6648587685 (step=0.01) 

与精确积分的数值相比较

36.6407572458