找回密码
 欢迎注册
查看: 17550|回复: 3

[讨论] Brent算法的一些细节问题(公式编辑好了)

[复制链接]
发表于 2011-4-26 13:51:57 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
本帖最后由 shingyuan 于 2011-4-26 15:30 编辑

我最近在研究指数函数方程的数值解法,我看的数是"Numerical Recipes in C", 第九章介绍了相关方法,我试验的结果是"Bisection"方法速度稍慢,"Section"方法有的时候区间会超出原始区间,带来一些问题。
Brent方法好像没有什么太大问题,所以我决定使用这种方法,这个算法的想法应该是对三个初始点进行二次插值,其零点解出为:
$x=b+\frac{\frac{f(b)}{f(a)}(\frac{f(a)}{f(c)}(\frac{f(b)}{f(c)}-\frac{f(a)}{f(c)})(c-b)-(1-\frac{f(b)}{f(c)})(b-a))}{(\frac{f(a)}{f(c)}-1)(\frac{f(b)}{f(c)}-1)(\frac{f(b)}{f(a)}-1)}$


对于有两个点相同的情形为:$x=b+\frac{\frac{f ( b )}{f ( a )}( b-a  )}{1-\frac{f ( b )}{f ( a t )}}$
这个值作为新的对根的近似估计,如果出现一些不好的情况,则使用二分法代替以上插值法

但该算法实现的时候,出现了这样的情况
  1. s=fb/fa;
  2.                         if(a==c)
  3.                         {
  4.                                 p=2.0*xm*s;
  5.                                 q=1.0-s;
  6.                         }
  7.                         else
  8.                         {
  9.                                 q=fa/fc;
  10.                                 r=fb/fc;
  11.                                 p=s*(2.0*xm*q*(q-r)-(b-a)*(r-1.0));
  12.                                 q=(q-1.0)*(r-1.0)*(s-1.0);
  13.                         }
复制代码
其中
  1. xm=0.5*(c-b);
复制代码
书上所给的代码,计算 P/Q的时候,P差了一个负号,相比较于公式。这是什么原因?

这里的判断也不是很好理解
  1. if(p>0.0 )
  2. {
  3.          q= -q;
  4.   }
复制代码
这里按照书上的说法是b经过小的修正P/Q后(P是x = b + */*的分子,Q是分母),是否会越过初始的区间,这样做是否是判断P/Q的符号?另外,判断后为啥将q变号?是否是补上前面缺少的一个负号,感觉不太好理解


下面有两句不太好理解的代码:
  1. min1=3.0*xm*q-fabs(tol1*q);
  2.                         min2=fabs(e*q);
复制代码
这两个极值算出来是什么意义?

下面接着的这个条件判断
  1. 2.0*p<(min1 < min2 ? min1 : min2)
复制代码
似乎也不太好理解,请教下大家,谢谢

附:为何 \left( \right)  \left[ \right] 这些会没有用??

附:算法的源代码
  1. #include <math.h>
  2. #include <stdio.h>
  3. #define ITMAX        100
  4. #define EPS 3.0e-8
  5. #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))

  6. double zbrent(double (*func)(double), double x1, double x2, double tol)
  7. {
  8.         int iter;
  9.         double a=x1,b=x2,c=x2,d,e,min1,min2;
  10.         double fa=(*func)(a),fb=(*func)(b),fc,p,q,r,s,tol1,xm;

  11.        
  12.         fc=fb;
  13.        
  14.         for (iter=1;iter<=ITMAX;iter++)
  15.         {
  16.                 if ((fb > 0.0 && fc > 0.0) || (fb < 0.0 && fc < 0.0))
  17.                 {
  18.                                 c=a;
  19.                                 fc=fa;
  20.                                 e=d=b-a;
  21.                 }
  22.                 if (fabs(fc) < fabs(fb))
  23.                 {
  24.                                 a=b;
  25.                                 b=c;
  26.                                 c=a;
  27.                                 fa=fb;
  28.                                 fb=fc;
  29.                                 fc=fa;
  30.                 }
  31.                 tol1=2.0*EPS*fabs(b)+0.5*tol;
  32.                 xm=0.5*(c-b);
  33.                 if(fabs(xm)<=tol1 || fb==0.0) return b;
  34.                
  35.                 if(fabs(e) >= tol1 && fabs(fa) > fabs(fb))
  36.                 {
  37.                         s=fb/fa;
  38.                         if(a==c)
  39.                         {
  40.                                 p=2.0*xm*s;
  41.                                 q=1.0-s;
  42.                         }
  43.                         else
  44.                         {
  45.                                 q=fa/fc;
  46.                                 r=fb/fc;
  47.                                 p=s*(2.0*xm*q*(q-r)-(b-a)*(r-1.0));
  48.                                 q=(q-1.0)*(r-1.0)*(s-1.0);
  49.                         }
  50.                         if(p>0.0)
  51.                         {
  52.                                 q= -q;
  53.                         }

  54.                         p=fabs(p);
  55.                         min1=3.0*xm*q-fabs(tol1*q);
  56.                         min2=fabs(e*q);
  57.                         if(2.0*p<(min1 < min2 ? min1 : min2))
  58.                         {
  59.                                 e=d;
  60.                                 d=p/q;
  61.                         }
  62.                         else
  63.                         {
  64.                                 d=xm;
  65.                                 e=d;
  66.                         }
  67.                 }
  68.                 else
  69.                 {
  70.                         d=xm;
  71.                         e=d;
  72.                 }
  73.                 a=b;
  74.                 fa=fb;
  75.                 if(fabs(d)>tol1)
  76.                 {
  77.                         b+=d;
  78.                 }
  79.                 else
  80.                 {
  81.                         b+=SIGN(tol1,xm);
  82.                 }
  83.                 fb=(*func)(b);
  84.         }
  85.         return 0.0;
  86. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-4-26 14:59:06 | 显示全部楼层
...
附:为何 \left( \right)  \left[ \right] 这些会没有用??
shingyuan 发表于 2011-4-26 13:51


Web 上的 LaTeX 是简易版,为的是保证低带宽下满足基本的交流。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-4-26 15:01:30 | 显示全部楼层
Web 上的 LaTeX 是简易版,为的是保证低带宽下满足基本的交流。
gxqcn 发表于 2011-4-26 14:59


明白了,谢谢您。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-4-28 12:40 , Processed in 0.043663 second(s), 16 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表