c语言 - 牛顿方法的收敛和发散



我需要用牛顿法求arctan(x-e)的一个根,并证明存在这样的根其中,如果一个方法是收敛的,如果一个方法是发散的,那么推导出方程来求这个"a"然后解它。我写了一个程序,但是不知道如何找到这个&;a&;

#include <stdio.h>
#include <math.h>
double f(double x) ;
double fd(double x) ;
double newton(double x,double eps);
#define e 2.71828182845904523
int main() 
{
double x,eps=1.e-16 ;
printf("Enter x :") ;
scanf("%le",&x) ; 
printf("%le",newton(x,eps)) ;

return 0;
}

double f(double x)
{
double z ;
z=atan(x-e);
return z ; 
}
double fd(double x)
{
double z ;
z=1/((x-e)*(x-e)+1);
return z ; 
}

double newton(double x,double eps)
{
double x1 ;   

while(1)
{
x1=x-f(x)/fd(x) ;
if(fabs(x1-x)<eps) return x1 ; 
x=x1 ;
}

return x1 ; 
}

证明存在这样的a,如果|x-e|<a方法收敛

牛顿方法近似解时附近正确的解决方案。

牛顿法在候选解发散或振荡时失效。

添加发散测试(例如:a变为非数字或无穷大)和循环迭代限制。

使用二分搜索来找到a的上界:在接近解(a = e)和发散解(a = e + 100)之间。见下文.

重复(对a_min, a_max角色和初始值进行代码调整)以找到a的下界。没有显示,留给OP去找。(我发现低侧a在1.0到1.5的范围内)

int main() {
double x, eps = 1.e-16;
printf("Enter x :n");
//scanf("%le", &x);
x = e*1.0001;
printf("%len", newton(x, eps));
double a_min = e;
double a_max = e + 100.0;
double a;
while (1) {
a = a_min + (a_max - a_min)/2;
if (a == a_min) break;
else if (a == a_max) break;
if (a_min >= a_max) break;
printf("a_min:%20e a_max:%20e a:%20en", a_min, a_max, a);
if (isnan(newton(a, eps))) {
a_max = a;
} else {
a_min = a;
}
}
printf("a high side:%en", a);
return 0;
}
double newton(double x, double eps) {
double x1;
int i;
for (i=10; i>0; i--) {
//printf("%2d %20e %20e %20en", i, x, fd(x), f(x));
if (isnan(x)) return x;
x1 = x - f(x) / fd(x);
if (fabs(x1-x) < eps)
return x1;
x = x1;
}
return 0.0/0.0;
}

结果

Enter x :
2.718282e+00
a_min:        2.718282e+00 a_max:        1.027183e+02 a:        5.271828e+01
a_min:        2.718282e+00 a_max:        5.271828e+01 a:        2.771828e+01
a_min:        2.718282e+00 a_max:        2.771828e+01 a:        1.521828e+01
a_min:        2.718282e+00 a_max:        1.521828e+01 a:        8.968282e+00
a_min:        2.718282e+00 a_max:        8.968282e+00 a:        5.843282e+00
a_min:        2.718282e+00 a_max:        5.843282e+00 a:        4.280782e+00
a_min:        2.718282e+00 a_max:        4.280782e+00 a:        3.499532e+00
a_min:        3.499532e+00 a_max:        4.280782e+00 a:        3.890157e+00
a_min:        3.890157e+00 a_max:        4.280782e+00 a:        4.085469e+00
a_min:        4.085469e+00 a_max:        4.280782e+00 a:        4.183126e+00
a_min:        4.085469e+00 a_max:        4.183126e+00 a:        4.134297e+00
a_min:        4.085469e+00 a_max:        4.134297e+00 a:        4.109883e+00
...
a_min:        4.104323e+00 a_max:        4.104323e+00 a:        4.104323e+00
a high side:4.104323e+00

推导出这个等式并解决它

"Derive"——比;当,更有趣的模拟上面找到它。

考虑两个x:x_lo,x_hi和牛顿迭代x_better(x) = x - f(x)/f'(x)

next_better(x_lo) == next_better(x_hi)x_lo < x_hi处于振荡对

休息一下,我要走了

double x在C语言中意味着只在内存上推进堆栈。如果你不填0,它只会占用x下的内存值。

一个改进:double x = 0或您想要的值。它会将8个字(1字= 8位)填充到0x00000000,而不是像0x2409caf42或idk这样的随机数据

f(x)/df(x)最小化函数。但是如果你最小化导数,你会发现一个根f。

df (x)/地区指定基金(x)

  • 如果你使用f(x)/df(x),最简单的方法是梯度下降:x -= 0.001*f(x)/df(x)

相关内容

  • 没有找到相关文章

最新更新