2011-03-06 102 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