I need to integrate a function which has a factorial in its expression. But, if you try to evaluate factorial, when n > 170, R returns Inf.
I found a lot of packages that allow you to calculate very large numbers, however, they always returns an object from a class that I can't integrate. The final result from the integral always will be a small number.
Here's my code:
integrand <- function(n, i, x) {
(factorial(n) / (factorial(i - 1) * factorial(n - i))) *
x^(i - 1) * (1 - x)^(n - i)
}
forder <- function(Fx, x, n, i, ...) {
lower <- sapply(x - 1, Fx, ...)
upper <- sapply(x, Fx, ...)
integrate(integrand,
lower = lower, upper = upper, n = n, i = i,
stop.on.error = FALSE)$value
}
forder <- Vectorize(forder, "x")
##------------------------------------------------------------------------------
## Some example
y <- sort(rpois(100, 1))
## Works fine
forder(ppois, y, 170, 10, lambda = 1)
## Does not work
forder(ppois, y, 171, 10, lambda = 1)
##------------------------------------------------------------------------------
As said in my comment, you can replace (factorial(n) / (factorial(i - 1) * factorial(n - i)))
with i*choose(n, i)
. These two quantities are equal but choose(n,i)
allows higher values of n
.
Or you can use the pbeta
function instead of doing a numerical integration:
forder <- function(Fx, x, n, i, ...) {
lower <- sapply(x - 1, Fx, ...)
upper <- sapply(x, Fx, ...)
i*choose(n, i) * (pbeta(upper, i, n-i+1) - pbeta(lower, i, n-i+1)) * beta(i, n-i+1)
}
Even better, use logarithms:
forder <- function(Fx, x, n, i, ...) {
lower <- sapply(x - 1, Fx, ...)
upper <- sapply(x, Fx, ...)
lg <- log(i) + lchoose(n, i) +
log(pbeta(upper, i, n-i+1) - pbeta(lower, i, n-i+1)) + lbeta(i, n-i+1)
exp(lg)
}
I didn't notice this simplification: i*choose(n, i) * beta(i, n-i+1) = 1
. So you can simply do:
forder <- function(Fx, x, n, i, ...) {
lower <- sapply(x - 1, Fx, ...)
upper <- sapply(x, Fx, ...)
pbeta(upper, i, n-i+1) - pbeta(lower, i, n-i+1)
}