2011-03-06 89 views
0

的零,我嘗試使用二分法指出,找到一個函數的根:查找根/功能

if f(a)*f(b) < 0 then a root exists, 
then you repeat with f(a)*f(c)<0 where c = (a+b)/2  

但林不知道如何修復代碼,以便它工作正常。 這是我的代碼,但它無法正常

from scipy import * 
from numpy import * 


def rootmethod(f, a, b, tol): 


    x = a 
    fa = sign(eval(f)) 

    x = b 
    fb = sign(eval(f)) 

    c = a + b 
    iterations = 0 

    if fa == 0: 
     return a 
    if fb == 0: 
     return b 

    calls = 0   
    fx = 1 

    while fx != 0: 
     iterations = iterations + 1 
     c *= 0.5 
     x = a + c 
     fc = sign(eval(f)) 
     calls = calls + 1 

     if fc*fa >= 0: 
      x = a 
      fx = sign(eval(f)) 
     if fc == 0 or abs(sign(fc)) < eps: 
      fx = sign(eval(f)) 
      return x, iterations, calls 





print rootmethod("(x-1)**3 - 1", 1, 3, 10*e-15) 

新的編輯工作..但仍然不起作用

if fa*fb < 0: 

     while fx != 0: 
      iterations = iterations + 1 
      c = (a + b)/2.0 
      x = c 
      fc = sign(eval(f)) 
      calls = calls + 1 

      if fc*fa >= 0: 
       x = c 
       fx = sign(eval(f)) 
      if fc == 0 or abs(sign(fc)) < tol: 
       fx = sign(eval(f)) 
       return x, iterations, calls 

編輯:改變C =(A + B)* 2到c =(A + b)/ 2在該方法的描述中。

+0

你能明確指出哪裏出了問題嗎?即解釋器錯誤消息,不正確的輸出(如果是這樣,示例輸入/輸出) – 2011-03-06 02:38:04

+0

嗨,例如..這個輸入..(「x ** 3 - 4 * x ** 2 + 2 * x -4」,2, 5,10 * e-15)給出(2,1,1)其中2是根,但正確的答案是3.75 ..它不會到達,也不會超過1 – Kartik 2011-03-06 02:43:49

+1

abs(sign(fc)) 2011-03-06 02:58:14

回答

0

坦白說你的代碼有點亂。這是一些有效的。閱讀循環中的註釋。 (BTW解決您給出的函數是2,而不是3.75)

from scipy import * 
from numpy import * 


def rootmethod(f, a, b, tol): 


    x = a 
    fa = sign(eval(f)) 

    x = b 
    fb = sign(eval(f)) 

    c = a + b 
    iterations = 0 

    if fa == 0: 
    return a 
    if fb == 0: 
    return b 

    calls = 0   
    fx = 1 

    while 1: 
    x = (a + b)/2 
    fx = eval(f) 

    if abs(fx) < tol: 
     return x 

    # Switch to new points. 
    # We have to replace either a or b, whichever one will 
    # provide us with a negative 
    old = b # backup variable 
    b = (a + b)/2.0 

    x = a 
    fa = eval(f) 

    x = b 
    fb = eval(f) 

    # If we replace a when we should have replaced b, replace a instead 
    if fa*fb > 0: 
     b = old 
     a = (a + b)/2.0 




print rootmethod("(x-1)**3 - 1", 1, 3, 0.01) 
+0

哎呀,這就是我的意思。 – 2011-03-06 03:39:19

+0

當我說解決方案是3.75我指的是我發佈在同一評論中的功能..它不同於這個.. – Kartik 2011-03-06 03:39:25

+0

啊。抱歉。無論如何,這工作。嘗試一下。 – 2011-03-06 03:40:12

0

我覺得 一個問題是:

x = a + c 

由於c = (a + b)*.5,你不需要在這裏a ...添加

更新

你不似乎沒有檢查是否fa * fb < 0開始,我也看不到你在哪裏縮小範圍:你應該重新分配abc,然後重新計算c

代碼這已經有一段時間,因爲我跟蟒蛇上次播放的,所以把它與鹽^ _^

x = a 
fa = sign(eval(f)) 

x = b 
fb = sign(eval(f)) 

iterations = 0 

if fa == 0: 
    return a 
if fb == 0: 
    return b 

calls = 0   
fx = 1 

while fa != fb: 
    iterations += 1 
    c = (a + b)/2.0 
    x = c 
    fc = eval(f) 
    calls += 1 

    if fc == 0 or abs(fc) < tol: 
     #fx = fc not needed since we return and don't use fx 
     return x, iterations, calls 
    fc = sign(fc) 
    if fc != fa: 
     b = c 
     fb = fc 
    else 
     a = c 
     fa = fc 
#error because no zero is expected to be found 
+0

他不得不做那個操作(這是流程的遞歸),但它應該在循環結束時完成。它現在在哪裏,它會擾亂你的第一個計算。 – 2011-03-06 02:54:32

+0

@Scribble Master,如果'a'爲5,'b'爲7,那麼他開始在11處用'x'檢查,這沒有意義...... – jswolf19 2011-03-06 02:59:41

+0

這是真的,但他必須平均a和b後第一次檢查。這就是爲什麼我說他應該將該行移動到最後並將其更改爲c + = a – 2011-03-06 03:02:54

0

的糧食,我相信你的循環應該是這樣的(僞代碼,並留出一些檢查):

before loop: 
a is lower bound 
b is upper bound 
Establish that f(a) * f(b) is < 0 

while True: 
    c = (a+b)/2 
    if f(c) is close enough to 0: 
     return c 
    if f(a) * f(c) > 0: 
     a = c 
    else 
     b = c 

換句話說,如果中點是沒有答案的,然後使它根據其簽署新的終端之一。

+2

由於f作爲字符串傳入,所以'f(c)'不會工作。這裏是一個提示,OP - 能夠使用入站字符串作爲實際函數,將其添加到方法的頂部:'f = eval(「lambda x:」+ f)'這將從字符串轉換f ''(x-1)** 3-1「'執行該計算的可調用函數 - 那麼您可以直接調用'f(a)'和'f(b)'等,而不是'x = a',接着是'fa = eval(f)'。 – PaulMcG 2011-03-06 03:36:26

+0

@Paul McGuire:這種方式使用lambda很好。 – Vamana 2011-03-06 03:45:22

0

請注意,該代碼具有由四捨五入誤差簡單的缺乏

a=0.015707963267948963 
b=0.015707963267948967 
c=(a+b)*.5 

c再次成爲b(一探究竟!)。 如果像1e-16那樣有很小的公差,你可以在無限循環 中結束。

def FindRoot(fun, a, b, tol = 1e-16): 
    a = float(a) 
    b = float(b) 
    assert(sign(fun(a)) != sign(fun(b))) 
    c = (a+b)/2 
    while math.fabs(fun(c)) > tol: 
    if a == c or b == c: 
     break 
    if sign(fun(c)) == sign(fun(b)): 
     b = c 
    else: 
     a = c 
    c = (a+b)/2 
    return c 

現在,一遍又一遍地調用eval並不是很有效率。 這裏是你可以做什麼,而不是

expr = "(x-1.0)**3.0 - 1.0" 
fn = eval("lambda x: " + expr) 
print FindRoot(fn, 1, 3) 

或者你可以把FindRoot內EVAL和lambda定義。

它對您有幫助嗎?

Reson