简体   繁体   English

如何在 R 的循环内将结果添加到向量中

[英]How to add Results into a Vector within a Loop in R

I was prompted a question and am ever so close to solving what I need.我被提示了一个问题,并且非常接近解决我需要的问题。 The question is as follows-问题如下——

"Write a while loop that computes and stores as a new object, the factorial of any non-negative integer mynum by decrementing mynum by 1 at each repetition of the braced code." “编写一个 while 循环,计算并存储为新的 object,任何非负 integer mynum 的阶乘,方法是在每次重复括号代码时将 mynum 减 1。”

Another factor was that if 0 or 1 was entered, the output would be 1.另一个因素是,如果输入 0 或 1,则 output 将为 1。

The code that I wrote as follows-我写的代码如下-

factorialcalc <- function(i){
  factorial <- 1
  if(i==0 | i==1){
    factorial <- 1
  } else{
    while(i >= 1){
      factorial <- factorial * i
      i <- i-1
    }
  }
  return (factorial)
}

with inputs-与输入-

mynum <- 5
factorialcalc(mynum)

and output-和输出-

[1] 120

You may be wondering, "your code works perfect, so what's the issue?"您可能想知道,“您的代码运行良好,那么问题出在哪里?” My issue lies in the part of the question that says "computes AND stores."我的问题在于“计算和存储”的问题部分。

How can I modify my code to put the answers of factorialcalc into a vector?如何修改我的代码以将 factorialcalc 的答案放入向量中?

Example- I input示例-我输入

mynum <- 5
factorialcalc(mynum)

and

mynum <- 3
factorialcalc(mynum)

and

mynum <- 4
factorialcalc(mynum)

When I call this new vector, I would like to see a vector with all three of their outputs (so almost like I made a vector c(120,6,24))当我调用这个新向量时,我希望看到一个包含所有三个输出的向量(就像我制作了一个向量 c(120,6,24))

I'm thinking there's a way to add this vector somewhere in my function or while loop, but I'm not sure where.我在想有一种方法可以在我的 function 或 while 循环中的某处添加这个向量,但我不确定在哪里。 Also, please note that the answer must contain a loop like in my code.另外,请注意答案必须包含我的代码中的循环。

The answer I would be looking for would have an empty vector say answers <- c() , and every time I were to run the function factorialcalc , during the function, I would add the return results from factorial into this new answers vector.我要寻找的答案将有一个空向量说answers <- c() ,并且每次我要运行 function factorialcalc ,在 function 期间,我会将factorial的返回结果添加到这个新的answers向量中。

I've tried putting in something like this-我试过放这样的东西-

factorialcalc <- function(i){
  factorial <- 1
  answers <- c()
  answers[i] <- answers[factorial]
  if(i==0 | i==1){
    factorial <- 1
  } else{
    while(i >= 1){
      factorial <- factorial * i
      i <- i-1
    }
  }
  return (factorial)
}

This doesn't seem to work, but I think the idea is there.这似乎不起作用,但我认为这个想法是存在的。

Thanks in advance for any help.提前感谢您的帮助。

Here is a solution that illustrates how to build a vector of results for a factorial function.这是一个解决方案,说明了如何为阶乘 function 构建结果向量。 We use the testthat package to build unit tests for the function.我们使用testthat测试为 function 构建单元测试。

Rather than iterating from i down to 1, we iterate from 2 to i , using the j-1 value in the output vector to multiply by the current number in the for() loop.我们不是从i迭代到 1 ,而是从 2 迭代到i ,使用 output 向量中的j-1值乘以for()循环中的当前数字。

We also include error checking at the top of the function.我们还在 function 的顶部包括错误检查。 Since R does not have a way to directly validate a numeric vector as an integer / whole number, we compare the absolute value of the input minus its rounded value to machine precision and stop if the comparison fails.由于 R 无法直接将数字向量验证为 integer / 整数,因此我们将输入的绝对值减去其舍入值与机器精度进行比较,如果比较失败则停止。

factorial <- function(i){
     # return a vector of factorial values from 1 to i, where
     # i represents the i-th value in the factorial series 
     
     # first, validate the input 
     if(!is.numeric(i)) stop("i must be a whole number")
     if(!(abs(i - round(i)) < .Machine$double.eps^0.5)) stop("i must be a whole number")
     if (i < 0) stop("i must be a whole number")

     # now, process based on value of i 
     if (i %in% c(0,1)) return(1)
     resultVector <- 1
     # if we get here, i is greater than 1
     for(j in 2:i) resultVector <- c(resultVector,resultVector[j-1]*j)
     resultVector
}

We test the function with a variety of tests, ranging from invalid input handling to confirming the output of the function with known values.我们通过各种测试来测试 function,范围从无效输入处理到确认 function 的 output 具有已知值。 We also compare the length of the output vector to the input value of i .我们还将 output 向量的长度与i的输入值进行比较。

library(testthat)
test_that("Factorial function works",{
     expect_error(factorial(-3),"i must be a whole number",ignore.case=TRUE)
     expect_equal(1,factorial(0))
     expect_equal(1,factorial(1))
     expect_equal(c(1,2),factorial(2))
     expect_equal(c(1,2,6),factorial(3))
     expect_equal(c(1,2,6,24),factorial(4))
     expect_equal(c(1,2,6,24,120),factorial(5))
     expect_equal(5,length(factorial(5))) # test that length matches input i
     expect_error(factorial(3.1),"i must be a whole number",ignore.case=TRUE)
     expect_error(factorial("zzz"),"i must be a whole number",ignore.case=TRUE)
     
     
})

...and the test results: ...和测试结果:

==> Testing R file using 'testthat'

✓ |  OK F W S | Context
✓ |  10       | factorial

══ Results ═════════════════════════════════════════════════════════════════════
Duration: 0.2 s

OK:       10
Failed:   0
Warnings: 0
Skipped:  0

Test complete

Finally, we run the function multiple times to illustrate its output:最后,我们多次运行function来说明它的output:

> lapply(1:8,factorial)
[[1]]
[1] 1

[[2]]
[1] 1 2

[[3]]
[1] 1 2 6

[[4]]
[1]  1  2  6 24

[[5]]
[1]   1   2   6  24 120

[[6]]
[1]   1   2   6  24 120 720

[[7]]
[1]    1    2    6   24  120  720 5040

[[8]]
[1]     1     2     6    24   120   720  5040 40320

Consider Reduce first as replacement of your method:首先考虑Reduce作为您的方法的替代:

Reduce(`*`, 1:5)
# [1] 120

To extend incrementally, pass a sequence with Reduce inside an apply function (only mapply needs adjustment due to multiple elements):要增量扩展,请在 apply function 中传递一个带有Reduce的序列(由于多个元素,只有mapply需要调整):

factorialcalc <- function(i) Reduce(`*`, 1:i)
    
sapply(1:5, factorialcalc)
# [1]   1   2   6  24 120

vapply(1:5, factorialcalc, integer(1))
# [1]   1   2   6  24 120

tapply(1:5, 1:5, factorialcalc)
#   1   2   3   4   5 
#   1   2   6  24 120 
    
factorialcalc <- function(i,j) Reduce(`*`, i:j)
mapply(factorialcalc, 1, 1:5)
# [1]   1   2   6  24 120    

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

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