C中的牛顿法

时间:2013-08-09 09:38:41

标签: c numerical-methods

我正致力于行星运动的3D模拟。我需要解决等式

  

np * t = x - e * sin(x)

在解决的那一刻,我知道np,t和e的值。 对于每个行星np(角速度)和e(行星轨道的偏心率)。 所以我需要在每个时刻解决这个等式,以了解行星的坐标。 t从1变为某个数字,比方说50。

我选择了牛顿方法,迭代数组的第一个值为np * t,并进行10次迭代。 我用wolframalpha检查代码的结果。 所以这是问题所在。对于50个t值(从1到50),我得到几乎所有正确的值。三个四个结果被误认为是最大1(它是可接受的)但是对于值12,(12 * 04 = x - 11 * sin(x),输入参数)我犯了很大的错误。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>

/* np*t = E - e*sin(E)*/
/* 0 = E - e*sin(E) - np*t */

double f(double np, double t, double e, double E){
  return E - e*sin(E) - np*t;
}

double f_prim(double np, double t, double e, double E){
  return 1.0 - e*cos(E);
}

double newton(double np, double t, double e){
  double xk = np*t, xk1;
  int i = 0;
  while(i < 10){
    xk1 = xk - f(np, t, e, xk)/f_prim(np,t,e,xk);
    xk = xk1;
    i++;
  }
  return xk1;
}

int main(int argc, char** argv){
  int i=12;
  for(i = 0; i < 50; i++){
    printf("Solution %d %.5f \n", i, newton(0.4,1.0*i,11.0));
  }
  return 0;
}

12的程序返回值是

  

解决方案12 41.00415

方程的最大解是14,6

有人能告诉我为什么我有12个大错误,以及如何解决它

编辑: 固定的迭代次数用于调试目的(对于100次迭代也是如此:()

EDIT2: 我在调用牛顿方法时错放了值的顺序。因此,e * sin(x)不应该在-.95和.95之间,但是要大得多,所以我得到的是一个非常小的衍生物,它在分裂时犯了错误。

2 个答案:

答案 0 :(得分:2)

牛顿方法对迭代初始值的选择非常敏感。在这种情况下,初始值4.8使函数的导数非常小。除以非常值会导致方法在第一次迭代时过度拍摄:

  

x 1 = 4.8 - (4.8 - 11 sin(4.8) - 4.8)/(1 - 11 cos(4.8))= -287.321177325

此函数上下移动很多,因此该方法可能永远不会与此初始值收敛。您可以应用多种技巧中的一种来选择更好的技巧:

  • 如果方法在几次迭代中没有开始收敛,则用随机数扰动初始值
  • 使用bisection method括起根,直到“足够接近”然后使用牛顿方法
  • 选择彼此靠近的三个点,为它们拟合二次多项式,并使用其中一个根作为初始值。

答案 1 :(得分:0)

如果方程有多个根,则无法确定从牛顿方法得到哪个根。由于你正在使用trig函数,你可能会有无穷多的根等式(编辑添加'可能',从注释中,问题中的等式具有有限数量的根)。

我很想将之前的结果用于xk的初始值而不是np * t。

您可以以图形方式显示计算,以验证是否确定了正确的根。

但这可能是数学堆栈交换网站上最好的问题。