牛頓迭代法求根


三次方根

(cube.pas/c/cpp

【問題描述】

自從在第2題中老師們的工作積極性提高以來,以Fengzee為首的學生們苦不堪言,因為老師給他們留了太多的作業,有些作業甚至是幾乎無法完成的。這次,數學老師布置下了10道開三次方的作業題,要求同學們筆算完成。Fengzee當然不會花時間做這種沒用的工作,他又沒有計算器。這樣的工作應當由電腦來完成,這就需要你編程序來解決。

    你的輸入文件中只含有一個實數n,是待開三次方的數字。你的任務是計算這個數的三次方根,並輸出在標准輸出文件中。我們有算法設計限制條件:這道題的主要運算過程,你必須自己在程序中設計,且評測時使用的編譯器已經去掉頭文件math.h,就是說,你不能使用這個頭文件中提供的一切函數。你只需要在文件中寫入結果,不要加任何額外的文字。在滿足算法設計限制條件的前提下,你的答案只需與標准答案相差不超過0.001,你即可得到全部的分數;而且你輸出的數字的小數位數不受限制(小數點保留六位)。

【輸入文件】輸入文件cube.in

輸入文件中只含有一個實數n,是待開三次方的數字。

【輸出文件】輸出文件cube.out

數n的三次方根

【樣例輸入】

9

【樣例輸出】

2.08008  

【數據規模】

-10000<=n<=10000  

  一般實現

二分逼近法  (同學友愛的代碼~)

#include <cstdio>
#include <iostream>
#include <algorithm>
#define eps 1e-8

using namespace std;

double n;

double fun(double mid)
{return mid*mid*mid<n?1:0;}

int main()
{
    cin>>n;
    double l=0,r=n,mid;
    if(n<0) swap(l,r);
    while(r-l>eps){              //當精度未達到1e-8即10-8時,二分逼近
        mid=(l+r)/2;
        if(fun(mid)) l=mid;     //小的話 
        else r=mid;
    }
    printf("%.6f\n",r);
}

然而我並沒有想到這一點

反而想起牛頓老人家了

我要在巨人的肩膀上干事!!(其實是我蠢 =6=..)

沒錯 牛頓迭代法

定義 一種在實數域和復數域上近似求解方程的方法  --摘自百度

原理  不斷用(x,f(x))的切線來逼近方程的根

遞推公式  (證明過程可詳見百度)

加深理解可以參考 如何通俗易懂的講解牛頓迭代法

有了這個我們可以干什么呢。

當然是去解方程啦

求解步驟:
1. 原函數: f(x)=xm-af(x)=xma
2. 原函數的導函數: f'(x)=mxm-1f(x)=mxm1
3. 使用牛頓迭代公式 

可得xn+1=xnf(xn)f(xn)=xnxmnamxm1n

對於本題而言 可以看成解方程 x^3=a

代入公式可得 xn+1=xn-(x3-a)/3xn2

如此自定義一個函數就好了

注意:牛頓法只能逼近解,不能計算精確解。不過實際應用中,我們都不要求絕對精確的解,只要精度足夠高就好了  (所以此題我 wrong 了。)

#include <iostream>
#include <cstdio>
using namespace std;

int mabs(int a)
{
    if(a<0) a=-a;
    return a;
}
double sqrt(double c)
{
   double err = 1e-8; //設立精度
   double t = c;
   while (mabs(c - t*t*t) > err)  t =t-(t*t*t-c)/(3.000*t*t); //三次方的遞推公式
   return t;
}
int main()
{
        int n;
        cin>>n;
    printf("%.6lf",sqrt(n));
    return 0;
}

 輸入值 9 輸出值2.099878 誤差有點大。

不過可以通過調參數來調整

同樣的利用牛頓迭代法可以推導到一般情況,大家可以嘗試一下。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM