牛顿迭代法解指数方程(aX + e^x解 = b )

 

    高中好友突然问我一道这样的问题,似乎是因为他们专业要做一个计算器,其中的一道习题是要求计算器实现这样的功能。   

    整理一下要求:解aX + e^X = b 方程。解方程精度要求0.01,给定方程只有一解,a>0,b>0,0<X<20。

    当被第一次问及这样一个问题的时候,我脑海里反映的第一个方法就是「牛顿迭代法(NewtonMethod」。然而自己算法功底太差了,从来没有真正去了解过牛顿迭代法,反正早晚都是要学的,正好便借着这个机会学习了一个。    

    我一直认为牛顿迭代法的效率应该是几个近似求解方程的最快方法,于是查了一下百度百科后进行了实现。

    实现代码如下:

 

 1 #include<stdio.h>
 2 #include<math.h>
 3 #define MAX 20 
 4 #define MIN 0
 5 #define MID 10
 6 #define eps 1e-2 
 7 #define fx a*x+exp(x)-b
 8 #define fdx a + exp(x)
 9 double a,b,x;
10 double binary() ; // 二分查找
11 double NewtonMethod() ; // 牛顿迭代法 
12 int main()
13 {
14 scanf("%lf%lf",&a,&b);
15 printf("%.2lf\n",binary()) ;
16 printf("%.2lf\n",NewtonMethod()) ;
17 return 0 ;
18  } 
19  
20 double binary()   // 二分查找 
21 {
22   x = MID ;
23 double x1 =MIN , x2 = MAX ;
24 while( fabs(fx) > eps)
25  {
26   if( fx < 0)
27    x1 = x ;
28   if( fx > 0)
29    x2 = x ;
30   x = ( x1 + x2) / 2 ; 
31  }
32 return x ;
33 }
34 
35  
36 
37 
38 double NewtonMethod() // 牛顿迭代
39 {
40   x =  10 ; 
41 while(1)
42  {
43 if( fabs(fx) > eps )
44   { 
45         x = x - (fx) / (fdx);
46      }
47 else return x ;
48  }
49 }

 

 

网上普遍都是牛顿迭代法求解一元二次方程或者平方根,我于是照猫画虎根据牛顿迭代法的核心x1=x0 - f(x) / f'(x)  照猫画虎学习了一个。关于证明还不是太会,自己手画了一下发现这样的方法近似非常快,我记得曾今刚看到过资料说两次迭代好像eps就可以小于多少……

自己代码功底还是太差了,二分也写跪多次,写出了什么if (fx < 0 ) x = ( x + MAX ) / 2这样现在看来有点羞耻想笑的代码。最后遇到最大的一个问题是在牛顿迭代法 fx / fdx 因为fx和fdx是用宏定义的,直接展开后导致运算优先级出现了问题然后各种程序跑崩……所以这里宏定义以后要考虑加括号,要认真考虑优先级问题,不然出了问题感觉挺难发现的。

以前前辈们总说代码要多写多练多手敲,就算把书上代码照抄到电脑上都是很好的。一直不能理解,觉得这样做没什么意义。现在深刻感觉到,代码看再多遍不如自己手写一遍,算法理论知道再清楚,不多手写几次就不知道坑在哪里,就实现不出来。以后一定多写代码。

 

不过最后有一个问题我一直不能理解:

 

为了比较其与二分的效率,我写了一个随机器准备对拍一下:

 1 #include<iostream>
 2 #include<ctime>
 3 #include<cstdlib>
 4 using namespace std ; 
 5 int main()
 6 {
 7 srand((int) time(0) ) ;
 8 freopen("a.out","w"
 9  ,stdout) ;
10 for( int x = 0 ; x <= 10000  ; x++)
11   cout << rand() % 20  + 1 <<' ' << rand() % 20  + 1<<endl ;
12 return 0 ; 
13 }
14 
15  

 

产生了一万组 1 - 20 的数据文件,然后重定向到文件分别跑了一下数据,利用<ctime>下的 (double ) clock() / CLOCK_PER_SEC 来计算时间。

测试结果如下:

一万组数据 牛顿迭代反而慢于二分,不知道是因为我的数据产生中没有考虑过有方程有没有解的情况,还是程序写的不好或者输入输出有问题……?

不太会分析两个这样的算法的时间复杂度,真诚询问。二分法我感觉应该是O(nlgn) ?不会证明牛顿迭代法……就更难分析牛顿迭代法了……理论上我感觉牛顿迭代法的性能应该优于二分法啊。不知道问题出在哪里了……

posted on 2016-12-20 21:35  Dark猫  阅读(1788)  评论(0)    收藏  举报

导航