如何将结果添加到 R 中循环内的向量中
How to add Results into a Vector within a Loop in R
我被提示了一个问题,并且非常接近解决我需要的问题。问题如下-
“编写一个 while 循环,通过在每次重复大括号代码时将 mynum 减 1 来计算和存储任何非负整数 mynum 的阶乘作为一个新对象。”
另一个因素是,如果输入 0 或 1,则输出将为 1。
我写的代码如下-
factorialcalc <- function(i){
factorial <- 1
if(i==0 | i==1){
factorial <- 1
} else{
while(i >= 1){
factorial <- factorial * i
i <- i-1
}
}
return (factorial)
}
有输入-
mynum <- 5
factorialcalc(mynum)
并输出-
[1] 120
您可能想知道,“您的代码运行完美,那么问题是什么?”
我的问题在于问题的“计算和存储”部分。
如何修改我的代码以将 factorialcalc 的答案放入向量中?
例子-
我输入
mynum <- 5
factorialcalc(mynum)
和
mynum <- 3
factorialcalc(mynum)
和
mynum <- 4
factorialcalc(mynum)
当我调用这个新向量时,我希望看到一个包含所有三个输出的向量
(所以几乎就像我制作了一个向量 c(120,6,24))
我想有办法在我的函数或 while 循环中的某处添加此向量,但我不确定在哪里。另外,请注意答案必须包含一个循环,就像我的代码中那样。
我要寻找的答案会有一个空向量,比如 answers <- c()
,每次我要 运行 函数 factorialcalc
,在函数执行期间,我都会添加return 来自 factorial
的结果进入这个新的 answers
向量。
我试过这样输入-
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)
}
这似乎行不通,但我认为这个想法是存在的。
在此先感谢您的帮助。
这是一个解决方案,说明了如何为阶乘函数构建结果向量。我们使用 testthat
包为函数构建单元测试。
我们不是从 i
迭代到 1,而是从 2 迭代到 i
,使用输出向量中的 j-1
值乘以 for()
循环。
我们还在函数的顶部包含了错误检查。由于 R 无法直接将数值向量验证为整数/整数,因此我们将输入的绝对值减去其舍入值与机器精度进行比较,如果比较失败则停止。
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
}
我们通过各种测试来测试该函数,从处理无效输入到确认具有已知值的函数输出。我们还将输出向量的长度与 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)
})
...以及测试结果:
==> 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
最后,我们多次运行这个函数来说明它的输出:
> 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
首先考虑 Reduce
来替代您的方法:
Reduce(`*`, 1:5)
# [1] 120
要逐步扩展,请在应用函数中传递带有 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
我被提示了一个问题,并且非常接近解决我需要的问题。问题如下-
“编写一个 while 循环,通过在每次重复大括号代码时将 mynum 减 1 来计算和存储任何非负整数 mynum 的阶乘作为一个新对象。”
另一个因素是,如果输入 0 或 1,则输出将为 1。
我写的代码如下-
factorialcalc <- function(i){
factorial <- 1
if(i==0 | i==1){
factorial <- 1
} else{
while(i >= 1){
factorial <- factorial * i
i <- i-1
}
}
return (factorial)
}
有输入-
mynum <- 5
factorialcalc(mynum)
并输出-
[1] 120
您可能想知道,“您的代码运行完美,那么问题是什么?” 我的问题在于问题的“计算和存储”部分。
如何修改我的代码以将 factorialcalc 的答案放入向量中?
例子- 我输入
mynum <- 5
factorialcalc(mynum)
和
mynum <- 3
factorialcalc(mynum)
和
mynum <- 4
factorialcalc(mynum)
当我调用这个新向量时,我希望看到一个包含所有三个输出的向量 (所以几乎就像我制作了一个向量 c(120,6,24))
我想有办法在我的函数或 while 循环中的某处添加此向量,但我不确定在哪里。另外,请注意答案必须包含一个循环,就像我的代码中那样。
我要寻找的答案会有一个空向量,比如 answers <- c()
,每次我要 运行 函数 factorialcalc
,在函数执行期间,我都会添加return 来自 factorial
的结果进入这个新的 answers
向量。
我试过这样输入-
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)
}
这似乎行不通,但我认为这个想法是存在的。
在此先感谢您的帮助。
这是一个解决方案,说明了如何为阶乘函数构建结果向量。我们使用 testthat
包为函数构建单元测试。
我们不是从 i
迭代到 1,而是从 2 迭代到 i
,使用输出向量中的 j-1
值乘以 for()
循环。
我们还在函数的顶部包含了错误检查。由于 R 无法直接将数值向量验证为整数/整数,因此我们将输入的绝对值减去其舍入值与机器精度进行比较,如果比较失败则停止。
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
}
我们通过各种测试来测试该函数,从处理无效输入到确认具有已知值的函数输出。我们还将输出向量的长度与 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)
})
...以及测试结果:
==> 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
最后,我们多次运行这个函数来说明它的输出:
> 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
首先考虑 Reduce
来替代您的方法:
Reduce(`*`, 1:5)
# [1] 120
要逐步扩展,请在应用函数中传递带有 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