使用递归实现log-gamma

时间:2018-01-21 20:22:19

标签: r recursion gamma

我正在尝试使用递归来计算lgamma。但它没有按预期工作,而是发出Nan-Inf。这可能是什么原因?

sum = 0
log_gamma_recursive <- function(n) {
  if(n == 1){
    return(1)
  }else{
    sum = sum + log(log_gamma_recursive(n-1))
    print(sum)
    return(sum)
  }
}#log 4  + log 3 + log 2 + log 1
log_gamma_recursive(5)

2 个答案:

答案 0 :(得分:1)

代码有三个问题:

  1. sum不应该是全局变量,因为连续的“外部”调用将返回累计值
  2. 您将返回值的log添加到sum。这将提供一系列嵌套日志:
    • 你得到log 4 + log(log 3 + log(log 2 + log (log 1)))),这显然是错误的
    • log(log 1) = log 0在数学上倾向于负无穷大,但图书馆可能会也可能不会将此归类为有效输入
  3. log_gamma(1)为0,而不是1
  4. 考虑到这一点,试试这个:

    log_gamma_recursive <- function(n) {
      if (n <= 1) {
        return (0)
      }else{
        sum = (log(n-1) + log_gamma_recursive(n-1))
        print(sum)
        return(sum)
      }
    }
    

答案 1 :(得分:1)

由于R可以执行向量化计算,因此可以安全地对结果向量和总和进行记录。

 ll=function(x)sum(log(1:(x-1)))

这有什么好处?这可以计算log_gamma_recursive无法计算的值。 Recall log_gamma_recursive是一个嵌套函数,因此在某些时候失败,具体取决于机器容量。例如:

log_gamma_recursive(3476)
[1] 24862.89
ll(3476)
[1] 24862.89

在此计算机中,log_gamma_recursive不适用于任何大于3476的数字:

log_gamma_recursive(3477)
Error: C stack usage  7970456 is too close to the limit

而另一方面,ll函数有效:

ll(3477)
[1] 24871.04

同时,ll函数比log_recursive函数快得多:

system.time(for(i in 1:10000)ll(3000))
   user  system elapsed 
  0.313   0.036   0.350 
system.time(for(i in 1:10000)log_gamma_recursive(3000))
   user  system elapsed 
 20.569   0.100  20.794 

这些单位在几秒钟内!!