在递归函数中收集cout或输出为向量

时间:2015-02-07 16:27:14

标签: c++ r rcpp

我有一个递归函数,它将树中节点中的一些打印为整数ids。将函数导出到R后,我无法将cout输出用于任何事情(或者看起来似乎如此)。理想的是,如果(1)我可以将输出作为向量返回,或者(2)在不损失太多速度的情况下解析R中的cout

我会在这里插入一些代码,但我的功能特别通用。基本上我试图将Fibonacci序列作为向量而不是求和返回,但是通过递归函数而不使用全局或静态变量。

例如,fib(6)将在R中返回:

[1] 0 1 1 2 3 5

所以可以,

y <- fib(6)

y[4]y[4:5]将分别返回

[1] 2

[1] 2 3

提前感谢解决问题的见解和想法。使用静态变量就像我自己一样。

3 个答案:

答案 0 :(得分:3)

我在Rcpp book的第一章中用R和C ++中的不同哈希和memoization实现详细讨论了这个问题。

答案 1 :(得分:1)

您应该阅读这本在线图书http://adv-r.had.co.nz/,主要是您的问题部分回答http://adv-r.had.co.nz/Function-operators.html的记忆部分:

只需添加函数fib3,例如:

library(memoise)

fib2 <- memoise(function(n) {
  if (n < 2) return(1)
  fib2(n - 2) + fib2(n - 1)
})

fib3 <- memoise(function(n) sapply(1:n, fib2))

#> fib3(6)
#[1]  1  2  3  5  8 13

答案 2 :(得分:1)

只是为了好玩,使用std::generate_n和函数对象(fseq)代替sapply的方法稍微复杂一点:

#include <Rcpp.h>

struct fseq {
  public: 
    fseq() {
      current = 0;
    }

    int operator()() {
      int val = fib(current);
      current++;
      return val;
    }

    int fib(int n) {
      if (n==0) return 0;
      if (n==1) return 1;
      return fib(n-2) + fib(n-1);
    }

  private:
    int current;
};

// [[Rcpp::export(".fib")]]
int fib(int n) {
  if (n==0) return 0;
  if (n==1) return 1;
  return fib(n-2) + fib(n-1);
}

// [[Rcpp::export]]
std::vector<int> fib_seq(const int n) {
  if (n < 1) throw std::invalid_argument("n must be >= 1");

  std::vector<int> seq;
  seq.reserve(n);

  std::generate_n(std::back_inserter(seq), n, fseq());
  return seq;
}

library(microbenchmark)
##
R>  fib_seq(6)
[1] 0 1 1 2 3 5

R>  all.equal(fib_seq(6),.fib_seq(6))
[1] TRUE

.fib_seq <- function(n) sapply(0:(n-1), .fib)
##
R>  microbenchmark(
    fib_seq(6),.fib_seq(6),
    times=1000L,unit="us")
Unit: microseconds
        expr    min      lq      mean median      uq      max neval
  fib_seq(6)  1.561  1.9015  3.287824  2.108  2.3430 1046.021  1000
 .fib_seq(6) 27.239 29.0615 35.538355 30.290 32.8065 1108.266  1000

R>  microbenchmark(
    fib_seq(15),.fib_seq(15),
    times=100L,unit="us")
Unit: microseconds
         expr    min      lq     mean  median      uq     max neval
  fib_seq(15)  6.108  6.5875  7.46431  7.0795  7.7590  20.391   100
 .fib_seq(15) 57.243 60.7195 72.97281 63.8120 73.4045 231.707   100

R>  microbenchmark(
    fib_seq(28),.fib_seq(28),
    times=100L,unit="us")
Unit: microseconds
         expr      min       lq     mean   median       uq      max neval
  fib_seq(28) 2134.861 2143.489 2222.018 2167.364 2219.400 2650.854   100
 .fib_seq(28) 3705.492 3721.586 3871.314 3745.956 3852.516 5040.827   100

请注意,这些函数已参数化以反映您的陈述

  

例如,fib(6)将在R内返回:

     

[1] 0 1 1 2 3 5