我试图通过使用二分法来找到函数的根,说明:
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 :(得分:0)
我认为你的一个问题是:
x = a + c
自c = (a + b)*.5
以来,您无需在此处添加a
...
<强>更新强>
您似乎无法检查fa * fb < 0
是否可以启动,而且我也看不到您缩小界限的位置:您应该重新指定a
或b
在循环中c
,然后重新计算c
。
代码自从我最后一次玩python以来已经有一段时间了,所以带上一粒盐^ _ ^
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
答案 1 :(得分: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 :(得分:0)
坦率地说,你的代码有点混乱。这是一些有效的。阅读循环中的注释。 (顺便说一下你给定函数的解是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)
答案 3 :(得分: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 )
或者您可以将eval和lambda定义放在FindRoot中。
有用吗?
Reson