如何在没有不必要溢出的情况下计算大阶乘的比率?

How can I compute ratios of large factorials without unnecessary overflows?

我正在编写一个程序(在 R 中,以防万一),我需要在其中计算元素向量的唯一排列数,其中可以包含重复值。 mathematical formula 很简单:元素总数的阶乘除以每个唯一元素计数的阶乘的乘积。然而,即使实际答案不是很大,天真地计算结果也很可能导致溢出。例如:

# x has 200 elements, but 199 of them are identical
x <- c(rep(1, 199), 2)
num_unique_permutations <- factorial(length(x)) / prod(factorial(table(x)))

如果这没有溢出,那么 num_unique_permutations 将是 200!/(199!*1!) = 200。但是,两者都是 200!和199!溢出 double 的最大值,因此实际结果为 NaN。只要答案本身不溢出,是否有一种好的方法可以始终避免溢出(或下溢)? (或者,只要它不在溢出的 length(x) 范围内?)


(请注意,R 在大多数数值计算中使用双精度数,但问题并非特定于双精度数。任何具有范围的数字类型都有同样的问题。另外,我不关心失去一点精度到浮点数学,因为我只是用它来获得一些粗略的上限。)

您可以使用 gmp 库。

library(gmp)
factorial(as.bigz(length(x))) / prod(factorial(as.bigz(table(x))))
#[1] 200

在基数 R 中使用 lfactorial 来计算分子和分母的对数。然后对适当的差取幂。

numer <- lfactorial(length(x))
denom <- sum(lfactorial(table(x)))
exp(numer - denom)
#[1] 200

这可以很容易地写成一个函数。

num_unique_permutations <- function(x){
  numer <- lfactorial(length(x))
  denom <- sum(lfactorial(table(x)))
  exp(numer - denom)
}

num_unique_permutations(x)
#[1] 200