MatLab——用二分法求f(x)=x-tan(x)的根

MatLab——用二分法求f(x)=x-tan(x)的根,matlab,bisection,Matlab,Bisection,我已经在MatLab中为二分法算法编写了一个代码。我基于教科书中给出的伪代码。到目前为止,这个算法对我所有的问题都很有效,但是当我被要求在区间[1,2]上找到f(x)=x-tan(x)的根时,我遇到了一些麻烦。我的代码如下: function x = bisection(a,b,M) f = @(x) x - tan(x); u = f(a); v = f(b); e = b-a; x = [a, b, u, v] if (u > 0 && v > 0) || (u

我已经在MatLab中为二分法算法编写了一个代码。我基于教科书中给出的伪代码。到目前为止,这个算法对我所有的问题都很有效,但是当我被要求在区间[1,2]上找到f(x)=x-tan(x)的根时,我遇到了一些麻烦。我的代码如下:

function x = bisection(a,b,M)
f = @(x) x - tan(x);
u = f(a);
v = f(b);
e = b-a;
x = [a, b, u, v]
if (u > 0 && v > 0) || (u < 0 && v < 0)
    return;
end;
for k = 1:M
    e = e/2;
    c = a + e;
    w = f(c);
    x = [k, c, w, e]
    if (abs(e) < 10^(-5) || abs(w) < eps)
        return;
    end
    if (w < 0 && u > 0) || (w > 0 && u < 0)
        b = c;
        v = w;
    else
        a = c;
        u = w;
    end
end
这显然是一个很大的偏差,因为我希望得到f(c)=0(上面向量中的第三个条目)


如果有人能就如何提高我的成绩给我任何帮助/提示,我将不胜感激。我对MatLab非常陌生,所以请把我当作新手:)。

让我们看看由二分法生成的
c
序列:

c =  1.5000
c =  1.7500
c =  1.6250
c =  1.5625
c =  1.5938
c =  1.5781
c =  1.5703
c =  1.5742
c =  1.5723
c =  1.5713
c =  1.5708
c =  1.5706
c =  1.5707
c =  1.5707
c =  1.5708
您可以看到它收敛到
pi/2
tan()
在这一点上有一个奇点,
x-tan(x)
。对分法收敛于这种奇异性,例如,也有人说过。这就是为什么
f(c)
处的函数值不接近零的原因。事实上,它应该是无穷大

其他建议:

我喜欢你的二分法。要使其以更通用的方式使用,您可以合并以下更改:

  • 使变量
    f
    成为函数参数。然后你可以用你的方法处理不同的问题 函数,而无需重新编写
  • 第一次分配
    x=[a,b,u,v]
    ,但随后
    x(1)
    是 迭代。我会让这更一致
  • 通过查看符号,您可以轻松测试
    f(a)
    f(b)
    是否具有不同的符号 产品
    p=f(a)*f(b)
    。对于
    p>0
    符号相等且没有根, 对于
    p<0
    而言,符号不同,对于
    p==0
    而言,
    f(a)
    f(b)
    为零,而 已经找到了根

让我们看一下由二分法生成的
c
序列:

c =  1.5000
c =  1.7500
c =  1.6250
c =  1.5625
c =  1.5938
c =  1.5781
c =  1.5703
c =  1.5742
c =  1.5723
c =  1.5713
c =  1.5708
c =  1.5706
c =  1.5707
c =  1.5707
c =  1.5708
您可以看到它收敛到
pi/2
tan()
在这一点上有一个奇点,
x-tan(x)
。对分法收敛于这种奇异性,例如,也有人说过。这就是为什么
f(c)
处的函数值不接近零的原因。事实上,它应该是无穷大

其他建议:

我喜欢你的二分法。要使其以更通用的方式使用,您可以合并以下更改:

  • 使变量
    f
    成为函数参数。然后你可以用你的方法处理不同的问题 函数,而无需重新编写
  • 第一次分配
    x=[a,b,u,v]
    ,但随后
    x(1)
    是 迭代。我会让这更一致
  • 通过查看符号,您可以轻松测试
    f(a)
    f(b)
    是否具有不同的符号 产品
    p=f(a)*f(b)
    。对于
    p>0
    符号相等且没有根, 对于
    p<0
    而言,符号不同,对于
    p==0
    而言,
    f(a)
    f(b)
    为零,而 已经找到了根

非常感谢您的意见和改进建议!真的很欣赏它-尤其是解释二分法将收敛到奇点的链接。我写这个方法的原因和我写的一样,而不是像你建议的那样使用产品f(a)*f(b),是因为我的书写了“最好使用符号(w)来确定函数是否在间隔内改变符号”≠ 符号(u),而不是u*w<0,因为后者需要不必要的乘法,并且可能导致下溢或溢出”。我同意,避免上溢和下溢肯定是一个问题。非常感谢您的输入和改进建议!真的很欣赏它-尤其是解释二分法将收敛到奇点的链接。我写这个方法的原因和我写的一样,而不是像你建议的那样使用产品f(a)*f(b),是因为我的书写了“最好使用符号(w)来确定函数是否在间隔内改变符号”≠ 符号(u),而不是u*w<0,因为后者需要一个不必要的乘法,并且可能导致下溢或上溢”。我同意,避免上溢和下溢肯定是一个问题。