R

时间:2018-05-21 16:41:08

标签: r function catalan

我正在尝试在R中编写一个函数,它将输入numb并输出相应的加泰罗尼亚数字。 有关您的信息,加泰罗尼亚数字的递归公式

C_0 = 1; 
C_n = {(4n - 2)*C_(n-1)}/(n+1)

我的代码如下,

catalan_num_recr <- function(numb){
  if (numb == 0){
    return(1)
  }
  else
    return(((4*numb-2)*catalan_num_recr(numb-1))/(numb+1))
}

当我运行该功能时,我明白了,

> catalan_num_recr(3)
[1] 5

哪个是对的。

AIM :但是,我想找一个范围的加泰罗尼亚数字, 我想找到像catalan_num_recr(1:10)这样的东西。

问题:这不适用于我的功能,我收到以下警告,

Warning messages:
1: In if (numb == 0) { :
  the condition has length > 1 and only the first element will be used

许多错误的值作为输出,

> catalan_num_recr(1:15)
 [1] 1.000000 2.000000 2.500000 2.800000 3.000000 3.142857 3.250000
 [8] 3.333333 3.400000 3.454545 3.500000 3.538462 3.571429 3.600000
[15] 3.625000

有人可以帮我修改我的功能/或帮我看清问题吗?

问候。

5 个答案:

答案 0 :(得分:2)

使用带有函数的Vectorize并返回一个新函数,该函数本质上是接受向量化输入的函数的包装器。计算实际上是由mapply重复执行的,所以它不会像写一个手工矢量化的函数一样快。

Vectorize(catalan_num_recr)(1:15)
 [1]       1       2       5      14      42     132     429    1430    4862
[10]   16796   58786  208012  742900 2674440 9694845

答案 1 :(得分:1)

您的功能目前不接受矢量输入。这可能有点令人困惑,因为许多函数(如数学运算符)默认为矢量化。您需要使用mapapply函数将该函数应用于向量的每个元素。这实际上是一个快速循环,purrr包具有一致的语法和类型稳定的优势。

catalan_num_recr <- function(numb){
  if (numb == 0){
    return(1)
  }
  else
    return(((4*numb-2)*catalan_num_recr(numb-1))/(numb+1))
}

purrr::map_dbl(1:15, catalan_num_recr)
#>  [1]       1       2       5      14      42     132     429    1430
#>  [9]    4862   16796   58786  208012  742900 2674440 9694845

reprex package(v0.2.0)创建于2018-05-21。

答案 2 :(得分:1)

您只需使用sapply系列中的apply等矢量化函数。

sapply(1:10,catalan_num_recr,USE.NAMES = F)

答案 3 :(得分:1)

您可以在数字向量

上使用sapply(或lapply
sapply(c(0:15), catalan_num_recr)

只需将输出放在数据框中即可查看数字

data.frame("n" = c(0:5), "cnr" = sapply(c(0:5), catalan_num_recr))

  n cnr
1 0   1
2 1   1
3 2   2
4 3   5
5 4  14
6 5  42

答案 4 :(得分:1)

首先,您收到的警告告诉您numb == 0 R只评估numb[1] == 0

虽然其他答案是正确的,但它们效率不高,因为您需要多次计算每个加泰罗尼亚语数字。 (对于加泰罗尼亚语(15)你需要计算加泰罗尼亚语(14),你已经计算过了)

我认为这是一个更好的版本,它会计算每个加泰罗尼亚语数字,直到最大数字,然后返回您要求的数字。

catalan <- function(numbs) {
   cat <- vector("numeric", length(max(numbs)) + 1)
   for (i in 0:max(numbs)) {
      if (i == 0) {
         cat[i+1] <- 1
      } else {
         cat[i+1] <- ((4*i - 2)*cat[i])/(i + 1)
      }
   }
   cat[numbs + 1]
}

> catalan(1:15)
 [1]       1       2       5      14      42     132     429
 [8]    1430    4862   16796   58786  208012  742900 2674440
[15] 9694845

这是catrvect = Vectorize(catalan_num_recr)

的小基准
microbenchmark::microbenchmark(catalan(1:100), catvect(1:100))
Unit: microseconds
           expr      min        lq      mean    median       uq
 catalan(1:100)   86.515   98.7565  127.3139  122.7665  141.423
 catvect(1:100) 4764.728 4947.3070 5661.0624 5124.3385 5647.238
       max neval
   276.825   100
 11009.428   100

当然,该功能现在不是递归的。