【问题标题】:Newton's Method in R Precision/OutputR精度/输出中的牛顿法
【发布时间】:2013-10-30 13:18:27
【问题描述】:

所以,我应该编写代码来执行牛顿法,以指定精度(公差)计算任意数的平方根。

这是我的代码:

MySqrt <- function(x, eps = 1e-6, itmax = 100, verbose = TRUE) {
  GUESS <- 11
  myvector <- integer(0)
  i <- 1
  if (x < 0) {
    stop("Square root of negative value")
  }
  else {
    myvector[i] <- GUESS

    while (i <= itmax) {
      GUESS <- (GUESS + (x/GUESS)) * 0.5
      myvector[i+1] <- GUESS

      if (abs(GUESS-myvector[i]) < eps) {
        break()
      } 

      if (verbose) {
        cat("Iteration: ", formatC(i, width = 1), formatC(GUESS, digits = 10, width = 12),     "\n")
      }

      i <- i + 1

    }
  }    
  myvector[i]
}

eps 是公差。当我使用该函数计算 21 的平方根时,我得到了以下输出:

> MySqrt(21, eps = 1e-1, verbose = TRUE)
Iteration:  1  6.454545455 
Iteration:  2  4.854033291 
Iteration:  3   4.59016621 

但是,我不确定该函数是否会停止执行迭代。有人可以验证我的代码是否正确吗?将不胜感激!

【问题讨论】:

  • 你认为它为什么会提前停止?您要求的公差为十分之一...all.equal(MySqrt(21, eps=1e-1), sqrt(21), tolerance=1e-1)TRUE
  • 对我来说它迭代了 6 次,打印输出 5 次,它看起来与 sqrt(21) 的 6 位数相同
  • > MySqrt(21, 0.01) 迭代:1 6.454545455 迭代:2 4.854033291 迭代:3 4.59016621 [1] 4.590166 是否应该进行第四次迭代?第 2 次和第 3 次迭代结果之间的差异不小于容差水平,因此仍应执行循环。但我不知道为什么它只在 3 次迭代时停止。
  • 而不是myvector[i],只需返回myvector,您就会看到全部内容。它实际上比它告诉你的迭代次数多 1 次。它停止了,因为myvector 的最后两个元素的绝对差异小于.01eps4.590166 vs 4.582582
  • 我的错。如果我们将详细设置为 TRUE,它只会显示到第 3 次迭代。第 4 次迭代仍然没有显示。

标签: r


【解决方案1】:

您的代码几乎是正确的。它正在迭代正确的次数。唯一的错误是您不会在 break 语句之后增加 i,因此您不会返回最新的近似值。相反,您将返回前一个。

为了验证它是否在正确的时间停止,您可以将跟踪线向上移动到中断上方。您还可以将GUESS-myvector[i] 添加到跟踪中,这样只要差异变得足够小,您就可以看到它停止。如果您这样做并运行该函数,那么它在正确的时间停止的事实以及它返回错误值的事实将是显而易见的:

> MySqrt(21,eps=1e-1)
Iteration:  1 6.454545 -4.545455 
Iteration:  2 4.854033 -1.600512 
Iteration:  3 4.590166 -0.2638671 
Iteration:  4 4.582582 -0.007584239 
[1] 4.590166

虽然您的代码(几乎)是正确的,但它并不是以非常好的 R 风格编写的。例如,除非您想返回整个估计向量,否则没有理由需要将它们全部保留。此外,与其使用 while 循环,不如使用 for 循环更有意义。这是您功能的一种可能的改进版本:

MySqrt <- function(x, eps = 1e-6, itmax = 100, verbose = TRUE) {
  GUESS <- 11
  if (x < 0) {
    stop("Square root of negative value")
  }
  for(i in 1:itmax){
      nextGUESS <- (GUESS + (x/GUESS)) * 0.5
      if (verbose)
        cat("Iteration: ", i, nextGUESS, nextGUESS-GUESS, "\n")

      if (abs(GUESS-nextGUESS) < eps) 
        break

      GUESS<- nextGUESS
    }
  nextGUESS
}

【讨论】:

  • 谢谢!仍然是 R 编码的新手,所以我仍然靠 Google 的 R 样式指南生存,但你帮了大忙!
猜你喜欢
  • 2012-04-10
  • 2013-10-24
  • 2011-06-26
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 2019-06-19
  • 2015-01-06
  • 2018-07-30
相关资源
最近更新 更多