三次方根
(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
2. 原函數的導函數: f'(x)=mxm-1f
3. 使用牛頓迭代公式
可得
xn+1=xn−f
對於本題而言 可以看成解方程 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 誤差有點大。
不過可以通過調參數來調整
同樣的利用牛頓迭代法可以推導到一般情況,大家可以嘗試一下。
