首页 文章

Matlab中的矢量没有填充正确的值

提问于
浏览
0

我试图测试在Matlab中使用两种方法查找函数根的效率 . 为了做到这一点,我计算每个方法所采用的迭代,然后将其绘制为各种容差值(f(root)与0的接近程度) . 出于某种原因,当我计算迭代值并将它们保存到向量时 - 因为不同的容差有不同的值 - 向量似乎只填充0.我对此感到困惑,因为我写的函数不应该是返回0作为迭代值 . 这是我的所有代码:

function cooldrive()
    a = 0.1; b = 3;
    tol = 0.01;
    L = 1:0.1:4;
    r_x = zeros(1, length(L));
    ctr = 1;
    for i=L
        [x, iter] = bis(a, b, tol, i);
        r_x(ctr) = x;
        ctr = ctr+1;
        b = x;
    end

    r_x = r_x.^2;
    figure
    plot(L, r_x, '.-b', 'markersize', 16)
    ylabel('Decay Rate, x^2'), xlabel('Length, L'), title('Cooling Rate')
    grid

    x = (a+b)/2;
    r_iter_newt = zeros(1, 8);
    r_iter_bis = zeros(1, 8);
    r_tol = zeros(1, 8);
    ctr = 1;
    for j=1:8
        tol = 10^(-1*j);
        [x_newt, iter_newt] = newt(x, tol, 1);
        [x_bis, iter_bis] = bis(a, b, tol, 1);
        b = x_bis;
        r_iter_newt(ctr) = iter_newt;
        r_iter_bis(ctr) = iter_bis;
        r_tol(ctr) = tol;
        ctr = ctr+1;
    end

    figure
    plot(r_tol, r_iter_newt, '.-r', 'markersize', 16)
    hold on
    plot(r_tol, r_iter_bis, '.-b', 'markersize', 16);
    hold off
return

%% Bisection Method 
function [x, iter] = bis(a, b, tol, L)
    iter = 0;
    z1 = coolfun(a, L);
    z2 = coolfun(b, L);
    if z1 * z2 > 0
        disp('Root may not exist')
        x = NaN;
        iter = NaN;
        return
    end

    x = (a+b)/2;

    while abs(coolfun(x, L)) > tol
        if (coolfun(a,L)*coolfun(x,L)) <= 0
            b = x;
        else
            a = x;
        end
        x = (a+b)/2;
        iter = iter + 1;
    end 
    %[x, iter] = bis(a, b, tol, L);
return 

%% Newton's Method
function [ox, iter] = newt(ix, tol, L)
    iter = 0;
    while abs(coolfun(ix, L)) > tol
        x_j = ix - (coolfun(ix, L)/coolfundx(ix, L));
        ix = x_j;
        iter = iter+1;
    end
    ox = ix;
return

%% Evaluate function
function val = coolfun(x, L)
    val = sin(x*L) + x*cos(x*L);
return

%% Evaluate Function's Derivative
function val = coolfundx(x, L)
    val = (L*cos(x*L)) - (L*x*sin(x*L)) + cos(x*L);
return

在上面的代码中,iter_bis的值总是0,所以r_iter_bis中的值是NaN,0,0,....我看不出发生这种情况的原因 .

1 回答

  • 1

    问题是你测试根存在 . 你有

    z1 = coolfun(a, L);
    z2 = coolfun(b, L);
    if z1 * z2 > 0
        disp('Root may not exist')
    

    但是,由于您尝试解决的功能不是单调的,因此可以使两个终点为正,但中间点为负(反之亦然) . 在这种情况下,存在多个零,但是您的测试表明它们没有,并且您的代码将停在那里 .

    问题实际上与方法有关 . 二分法对非单调函数不起作用 . 您必须知道,根据您的函数值是正还是负,哪种方式移动到接近零,但如果您的函数不是单调的,那么您不知道 .

    您需要限制二分搜索域以使该函数单调,或使用其他方法 .

相关问题