牛顿法的收敛和发散
Converges and diverges of Newton's method
我需要用牛顿法求arctan(x-e)的根并证明存在这样的“a”,如果|x-e|a方法发散,则推导出求方程
这个“a”并解决 it.I 写了一个程序,但不明白如何找到这个“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 ;
}
double x
在 C 中意味着只是在内存上推进堆栈。如果你不用 0 填充它,它只会取 x
.
下的值内存
一个改进:double x = 0
或您想要的值。它会将 8 个字(1 个字 = 8 位)填充到 0x00000000,而不是像 0x2409caf42 或 idk 这样的随机数据
f(x)/df(x) 最小化一个函数。但是如果你最小化导数,你实际上会找到一个根 f。
df(x)/ddf(x).
- 如果你使用f(x)/df(x),最简单的方法是梯度下降:
x -= 0.001*f(x)/df(x)
prove that exists such a
for which if |x-e|<a
method converges
当近似解接近正确解时,牛顿法有效。
当候选解发散或振荡时,牛顿法失败。
添加发散测试(例如: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("%le\n", 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:%20e\n", a_min, a_max, a);
if (isnan(newton(a, eps))) {
a_max = a;
} else {
a_min = a;
}
}
printf("a high side:%e\n", a);
return 0;
}
double newton(double x, double eps) {
double x1;
int i;
for (i=10; i>0; i--) {
//printf("%2d %20e %20e %20e\n", 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 the equation to find this "a" and solve it.
“派生” --> 该死的,像上面那样模拟更有趣。
考虑两个 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
时,我们处于振荡对
向左休息,前往 OP。该走了。
我需要用牛顿法求arctan(x-e)的根并证明存在这样的“a”,如果|x-e|a方法发散,则推导出求方程 这个“a”并解决 it.I 写了一个程序,但不明白如何找到这个“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 ;
}
double x
在 C 中意味着只是在内存上推进堆栈。如果你不用 0 填充它,它只会取 x
.
一个改进:double x = 0
或您想要的值。它会将 8 个字(1 个字 = 8 位)填充到 0x00000000,而不是像 0x2409caf42 或 idk 这样的随机数据
f(x)/df(x) 最小化一个函数。但是如果你最小化导数,你实际上会找到一个根 f。
df(x)/ddf(x).
- 如果你使用f(x)/df(x),最简单的方法是梯度下降:
x -= 0.001*f(x)/df(x)
prove that exists such
a
for which if|x-e|<a
method converges
当近似解接近正确解时,牛顿法有效。
当候选解发散或振荡时,牛顿法失败。
添加发散测试(例如: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("%le\n", 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:%20e\n", a_min, a_max, a);
if (isnan(newton(a, eps))) {
a_max = a;
} else {
a_min = a;
}
}
printf("a high side:%e\n", a);
return 0;
}
double newton(double x, double eps) {
double x1;
int i;
for (i=10; i>0; i--) {
//printf("%2d %20e %20e %20e\n", 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 the equation to find this "a" and solve it.
“派生” --> 该死的,像上面那样模拟更有趣。
考虑两个 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
时,我们处于振荡对
向左休息,前往 OP。该走了。