簡體   English   中英

遞歸函數幫助(Python)

[英]Recursive Function Help (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

我最初回答這是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

首先,校正后的歐拉積分方法可以保證從頭到尾真正地進行積分,並且如果浮點誤差加起來,則確實會在停止ε處添加一個附加積分點(大小為step,將積分間隔更改為stop + step結束)。針對這種情況。

回想一下,微分方程y'(x)= f(x,y(x)),y(x0)= y0的Euler積分通過重復計算來進行

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

在純積分問題中,f中沒有y,因此將f(x)從a積分到b從而初始化y = 0並反復應用

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

只要x小於b。 在最后一步中,當bh <= x <= b時,設置h = bx,以使積分過程精確地以(浮點)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 / A * exp(C * A)實際上知道該函數f(x)= C * exp(A * x)的積分,以便值是R(start,stop)= F(stop)-F(start),所以

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM