2012-08-03 131 views
1

我已經在MatLab中爲二等分算法編寫了一個代碼。我基於我的教科書中給出的僞代碼。到目前爲止,該算法對我所有的問題都很好,但是當我被要求在區間[1,2]上找到f(x)= x - tan(x)的根時,我有一些麻煩。我的代碼如下:MatLab - 用二分法找出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 

如果我在區間[1,2]有,比如說,15次迭代運行這個算法,我最後的答案是:

x = 

    1.0e+004 * 

    0.0015 0.0002 -3.8367 0.0000 

這顯然是路要走因爲我希望得到f(c)= 0(上面向量中的第三項)。

如果有人可以給我任何幫助/提示如何改善我的結果,我將不勝感激。我對MatLab很新,所以對待我作爲新手:)。

回答

4

讓我們來看看它是由二分法所產生的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/2tan()在這一點上有一個奇點,x - tan(x)也有一個奇點。例如,二分法收斂於這個奇點,也如here所述。這就是爲什麼f(c)的函數值不接近零的原因。實際上它應該是(正/負)無窮大。

其他建議:

我喜歡你的分法。爲了使其可以更通用地使用,您可以合併這些更改:

  • 使變量f成爲函數參數。然後,您可以使用不同的 函數的方法,而無需重新編寫它。
  • 第一次分配x = [a, b, u, v],但後面x(1)是 迭代次數。我會讓這個更一致。
  • 您可以通過查看產品p = f(a)*f(b)的標誌 輕鬆測試f(a)f(b)是否有不同的標誌。對於p > 0的標誌是相同的,沒有根, 爲p < 0的標誌不同,而p == 0或者f(a)f(b)爲零,而您 已經找到根。
+0

非常感謝您的意見和改進建議!真的很感謝它 - 尤其是解釋了二分法將收斂到奇點的鏈接。我寫這個方法的原因與我所做的一樣,而不是像你所建議的那樣與產品f(a)* f(b)一起寫,因爲我的書寫道「最好使用符號來確定函數是否改變符號間隔)≠sign(u),而不是u * w <0,因爲後者需要不必要的乘法並可能導致下溢或溢出「。 – Kristian 2012-08-03 19:31:52

+0

我同意,避免溢出和下溢肯定是一個問題。 – Mehrwolf 2012-08-03 19:34:07

相關問題