简体   繁体   English

R 中平方根的 Newton-Raphson 方法

[英]Newton–Raphson method for square root in R

I am a beginner in R and was asked to write the code to calculate square roots by the Newton–Raphson method in R.我是 R 的初学者,并被要求编写代码以在 R 中通过牛顿-拉夫森方法计算平方根。 I approached it as follows:我接近它如下:

square.root<-function(x,tol=1e-6,r=x/2)  #function to calculate the square roots
{
    n.iter=0  #number of iterations
    while(abs(r^2-x)>=tol)  #condition to check for a defined level of tolerance
    {
        r=(r+x/r)/2  #
        n.iter=n.iter+1  #number of iterations is incremented
    }
    output<-list(r,n.iter)
    names(output)<-c("x.sqrt","n.iter")
    return(output)
}

The above code is a prototype for the complete function in which, I plan to insert checks for the sanity of the arguments, eg, is the passed argument of the type a character or not, etc. Note that I haven't written those checks here.上面的代码是完整 function 的原型,我计划在其中插入检查 arguments 的健全性,例如,传递的参数是否为字符类型等。请注意,我没有编写这些检查这里。 This code works fine as shown below:此代码工作正常,如下所示:

square.root(10)
$x.sqrt
[1] 3.162278

$n.iter
[1] 4

square.root(99)
$x.sqrt
[1] 9.949874

$n.iter
[1] 6

square.root(100)
$x.sqrt
[1] 10

$n.iter
[1] 6

The only shortcoming of this code is: It doesn't work when the input is a numeric vector, as described by the output below:这段代码唯一的缺点是:当输入是数字向量时不起作用,如下面的 output 所述:

square.root(c(10,99,100))
$x.sqrt
[1]  3.162278  9.979213 10.030495

$n.iter
[1] 4

Warning messages:
1: In while (abs(r^2 - x) >= tol) { :
  the condition has length > 1 and only the first element will be used
2: In while (abs(r^2 - x) >= tol) { :
  the condition has length > 1 and only the first element will be used
3: In while (abs(r^2 - x) >= tol) { :
  the condition has length > 1 and only the first element will be used
4: In while (abs(r^2 - x) >= tol) { :
  the condition has length > 1 and only the first element will be used
5: In while (abs(r^2 - x) >= tol) { :
  the condition has length > 1 and only the first element will be used

Now, I want to add the functionality that even a vector can be passed as an argument.现在,我想添加甚至可以将向量作为参数传递的功能。 My thoughts were that I create a blank data frame named as output .我的想法是我创建了一个名为output的空白data frame Then iterate over the vector x elements and go on appending new rows to the data frame output .然后遍历向量x元素和 go 以将新行附加到数据帧output


What I tried:我尝试了什么:

I wrote the following code concerning the above 'thought'.我写了以下关于上述“想法”的代码。

square.root1<-function(x,tol=1e-6,r=x/2)#function to calculate the square roots
{
    output<-data.frame(x.sqrt=double(),n.iter=double())  #create a blank data frame
    n.iter=rep(0,times=length(x))  #a vector of zeroes
    i=1  #iteration counter
    while(i<=length(x))  #iterate through all the values of the vector
    {
        while(abs(r[i]^2-x[i])>=tol)  #the checking condition for the tolerance
        {
            r[i]=(r[i]+x[i]/r[i])/2
            n.iter[i]=n.iter[i]+1  #the number of iterations is incremented
        }
        result<-data.frame(r[i],n.iter)  #store the results in another data frame
        names(result)<-c("x.sqrt","n.iter")  #name the columns
        rbind(output,result)  #append the result data frame to the output data frame
        i=i+1  #iterate the looping counter
    }
    return(output)  #return the output data frame
}

Results and where I am stuck:结果和我卡在哪里:

I seem to have messed up somewhere.我似乎在某个地方搞砸了。 The code creates an output that I was unprepared for, even for a numeric value:该代码创建了一个我没有准备好的 output,即使是数值:

square.root1(5)
[1] x.sqrt n.iter
<0 rows> (or 0-length row.names)

Looking at the above output it seems that the control is not going inside the first while loop.查看上面的 output 似乎控件没有进入第一个while循环。 I am stuck as to how I can proceed to create this function that would allow a vector as an argument.我不知道如何继续创建这个允许向量作为参数的 function。 Any help/hints are highly appreciated.非常感谢任何帮助/提示。

Note: I am bound to use the while loop in this function.注意:我一定会在这个 function 中使用 while 循环。

Another note: This question might be similar, but it didn't solve the problem.另一个注意事项:这个问题可能类似,但它并没有解决问题。 Below is the output I obtained from running this code:以下是我通过运行此代码获得的 output:

MySqrt(c(99,10,100))
Iteration:  1           10  5.954545455  10.04545455
Iteration:  2         9.95  3.816967384  10.00010284
Iteration:  3  9.949874372  3.218424149           10
[1] 9.949874

This is pretty much the same result that I would have obtained from the first code I wrote for the square root with a vector as the argument.这与我从我为平方根编写的以向量作为参数的第一个代码中获得的结果几乎相同。

Using Vectorize is perhaps the easiest way to do it as per the comment, but it is also possible to make a couple of small changes to your original code so that everything works on a vector...根据评论,使用Vectorize可能是最简单的方法,但也可以对原始代码进行一些小的更改,以便一切都在矢量上运行......

square.root<-function(x, tol=1e-6, r=x/2)  #function to calculate the square roots
{
  n.iter=0  #number of iterations
  while(any(abs(r^2-x)>=tol))  #"any" added here - loops while any values greater than tol
  {
     n.iter=n.iter+(abs(r^2-x)>=tol)  #only increases n.iter for errors greater than tol
     r=(r+x/r)/2        #swapped with line above to get right value in n.iter calculation       
  }
  output<-list(r,n.iter)
  names(output)<-c("x.sqrt","n.iter")
  return(output)
}

square.root(c(10,99,100))
$x.sqrt
[1]  3.162278  9.949874 10.000000

$n.iter
[1] 4 6 6

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM