在R

时间:2018-10-17 19:38:07

标签: r while-loop numerical-methods newtons-method

Newton-Raphson方法的标签不正确,我实际上正在使用Secant方法;但是我没有创建新标签的声誉。

我想我离得并不远。我有一个名为ISO()的函数来计算流体动力学。它是非线性的,因此找到需要数值求解的方程式的根。我选择使用“割线法”,因为我认为它是我想做的最简单的方法。

我认为我遇到问题的是重新分配我用来开始迭代的初始“猜测”。我正在使用while循环,并且正在计算迭代次数。

sec <- function(x){

  Number_Of_Iterations = 0 # Starts the counter

  x1 = x
  x2 = 3*x

  while(x2 - x1 > 0.0001){ # This is how I'm trying to converge the points.

    Number_Of_Iterations = Number_Of_Iterations + 1

    # The secant function to determine a new x:

    x_new = x2 - ISO(x1)*(x2 - x1)/(ISO(x2) - ISO(x1))

    if(x2 - x_new > x_new - x1){ # These were the rules that I set to reassign the inital chosen values.

      x2 = x_new
      x1 = x1

    }else{

      x1 = x_new
      x2 = x2

    }

  }
  m_dot = x_new
  m_dot

}

运行此代码时,得到的迭代次数为1,并且m_dot的值等于与手动计算第一次迭代时获得的值不同的值。我已经检查过,我的ISO()函数返回的值与手工计算时相同,因此基础函数确实起作用,我只是认为我无法让sec()函数覆盖什么我写了。

非常感谢所有帮助。

2 个答案:

答案 0 :(得分:0)

我可以猜测发生了什么:初始点处的函数值具有相同的符号,因此割线根x_new在间隔[x1, x2]之外。然后,通过重新分配逻辑,您可以在下一次迭代x2<x1中获得该值,以便在间隔时间的测试中,差异x2-x1为负,因此小于正阈值。因此,一次迭代后退出,找不到根。

最可能的意图是所有比较都是针对长度的,即差异的绝对值。因此更改为

 while( abs(x2 - x1) > 0.0001){ # This is how I'm trying to converge the points.
    ...
    if( abs(x2 - x_new) > abs(x_new - x1) ){ # These were the rules that I set to reassign the inital chosen values.

顺便说一句:根据您的描述,ISO函数似乎很昂贵。一次存储其评估值,然后在需要时(主要在

中)重复使用这些值
x_new = x2 - y2*(x2 - x1)/(y2 - y1)

(请注意,我将错别字从y1校正为y2,您正在求解斜率(x2-x_new)/(y2-0) = (x2 - x1)/(y2 - y1)的相等性以找到割线根。)

因此,在循环的开始和内部设置y1=ISO(x1); y2=ISO(x2);会增加x值的重新分配,从而计算出y值。

   x2 = x_new; y2 = ISO(x_new);

分别

   x1 = x_new; y1 = ISO(x_new);

对于使用ISO函数的任何x值,这种方式都会被精确评估一次。

答案 1 :(得分:0)

不幸的是,我的问题不仅仅是编码问题;使用割线法时出现问题。我对迭代的初步估计使该函数分析了错误的范围。

LutzL给出的建议在回答我的问题上走了很长的路,abs()是必要的,并且他(或她)关于将函数从正割公式中删除的建议可能会使用更少的计算能力

这是我的工作代码:

sec <- function(x){

  x1 = x
  x2 = x/10 # I have changed the initial values so that x1 is the larger of the two initial estimates.

  while(abs(x2 - x1) > 0.0000001){ # This is how I'm trying to converge the points.

    # The secant function to determine a new x:

    x_new = x2 - square(x2)*(x2 - x1)/(square(x2) - square(x1))

    # I have changed from ISO(), to a simple quadratic formula, I named square(). This secant function works for all of
    # the functions I have since tested it on.

    if( abs(x2 - x_new) > abs(x_new - x1)){

      x2 = x_new

    }else{

      x1 = x_new

    }

  }

  m_dot = x_new
  m_dot

}

我之所以选择编写自己的正割公式而不是使用程序包中的内置函数,是因为此函数的创建非常简单,并且我认为使用我自己的代码比依赖于编写的程序包更有意义。其他人。

我希望这对其他刚接触编码的人有所帮助,并非常感谢那些提供了答案的人,尤其是LutzL,因为没有他们的建议,我认为我不可能像我那样快地解决这个问题。