递归函数帮助(Python)

时间:2014-03-05 05:20:38

标签: python recursion

好的,我使用递归函数创建了一个函数,如下所示。

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

2 个答案:

答案 0 :(得分: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被保存在函数的递归和BETWEEN CALLS之间。当我第一次运行你的代码时,我得到了:

>>> 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

答案 1 :(得分:0)

首先校正的Euler积分方法保证真正从开始到停止集成,并且如果浮点数在stop-epsilon(大小步长,将积分间隔改为停止+步骤结束)中添加额外的积分点错误总结了这种情况。

回想一下,微分方程y'(x)= f(x,y(x)),y(x0)= y0的Euler积分通过重复计算进行

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

在纯积分问题中,f中没有y,从a到b积分f(x)因此初始化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(开始),所以

import math

def radiationExposure2(start, stop, dummy):
    A=math.log(0.5)/5.27;
    C=10
    return C/A*(math.exp(A*stop)-math.exp(A*start))

if __name__ == "__main__":
    print radiationExposure2(0,5,1);
    print radiationExposure2(0,5,1);

返回的值用于Euler积分

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

与精确积分的数值

36.6407572458