Regula-Falsi算法?

我正在尝试实现Regula-Falsi算法来解决2(x^3)-x-2的等式,但问题是变量c值保持不变并且它没有改变,即使我的代码应该改变它。

 #include #include float fonc(float x) { int result; result=2*(pow(x,3))-x-2; return result; } int main(void) { float eps=pow(10,-4); int i=0; float a,b,c; a=1; b=2; do { c=((a*fonc(b))-(b*fonc(a)))/((fonc(b)-fonc(a))); if(fonc(c)*fonc(a)eps); printf("le nombre d'itération %d",i); } 

添加前言:即使所有数据类型都合适,所提出的算法可能出现什么问题?

与二分法相比,纯正则falsi不会强制区间长度为零。 如果使用单调和凸函数,则迭代将在仅改变几何收敛的区间的一侧时停止。

为了正确捕获此行为,应在计算后立即将中点c与两个间隔结束进行比较。 作为奖励点,检查c处的值是否足够小并且如果为真,则无论距离这个区间的末端有多远,也要打破迭代。

存在许多简单的技巧来迫使间隔长度为零。 复杂的技巧引领了布伦特的方法。 一个简单的技巧是伊利诺伊州的变种 在这些变体中,中点被认为是凸总和

 c = |f(b)|/(|f(a)|+|f(b)|) * a + |f(a)|/(|f(a)|+|f(b)|) * b 

由于af(a)和f(b)的符号相反,这相当于原始公式。 如果b侧没有改变,则通过减小函数值f(b),即乘以额外的权重因子,增加其在该凸总和中的重要性。


以下是伊利诺斯州的falsi变种(或假位置方法)的实现。 该算法在6次迭代中找到函数值为2.2e-6且长度为6e-7的封闭区间的解。

 #include #include float fonc(float x) { return (2*x*x-1)*x-2; } int main(void) { float eps=1e-6; int i=0; float a=1, fa = fonc(a); float b=2, fb = fonc(b); printf("\na=%10.7fb=%10.7f fa=%10.7f fb=%10.7f\n------\n",a,b, fa,fb); if(signbit(fb)==signbit(fa)) { printf("Attention, les valeurs initiales de 'fonc' n'ont pas de signe opposeés!\n"); } do { float c=(a*fb-b*fa)/(fb-fa), fc = fonc(c); if( signbit(fc)!=signbit(fa) ) { b=a; fb=fa; a=c; fa=fc; } else { a=c; fa=fc; fb *= 0.5; } i++; printf("\na=c=%10.7fb=%10.7f fa=fc=%10.7f fb=%10.7f",c,b, fc,fb); if(fabs(fc)eps); printf("\nle nombre d'itération %d\n",i); return 0; } 

输出是

  a= 1.0000000 b= 2.0000000 fa=-1.0000000 fb=12.0000000 ------ a=c= 1.0769231 b= 2.0000000 fa=fc=-0.5789710 fb= 6.0000000 a=c= 1.1581569 b= 2.0000000 fa=fc=-0.0512219 fb= 3.0000000 a=c= 1.1722891 b= 1.1581569 fa=fc= 0.0497752 fb=-0.0512219 a=c= 1.1653242 b= 1.1722891 fa=fc=-0.0003491 fb= 0.0497752 a=c= 1.1653727 b= 1.1722891 fa=fc=-0.0000022 fb= 0.0248876 a=c= 1.1653733 b= 1.1653727 fa=fc= 0.0000020 fb=-0.0000022 le nombre d'itération 6 

好的,只是为了纠正算法以实际执行它的意图:

除了将result类型从int更改为float ,还需要更改循环条件。 目前它是:

  while ( fabs( b - c ) > eps ); 

这意味着循环将继续发生,直到值bc之间的距离变得低于0.0001 ,并且在这种情况下,目前,至少在我的结束时,代码将永远运行。

我们不是在减少bc之间的差异之后。 我们真正 fonc( c ) = 2*c*c*c - c - 2fonc( c ) = 2*c*c*c - c - 2小于我们的eps 。 最后,我们希望它尽可能接近零,以便c成为函数的根。 如此简单:

  while ( fabs( fonc( c ) ) > eps ); 

是我们应该的条件。 这样,随着int --> float更改,它不会陷入无限循环,在14次迭代中完成作业。

一个问题是resultint 。 你几乎肯定想floatdouble ,否则fonc()的结果会被截断为整数。