问题描述
我正在编写一个程序(如果需要的话,请用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!溢出两倍的最大值,因此实际结果为NaN。只要答案本身不溢出,是否有一个很好的方法可以始终避免溢出(或下溢)进行此计算? (或者也许,只要它不在length(x)
溢出的范围之内?)
(请注意,R在大多数数值计算中都使用双精度数,但是问题并不特定于双精度数。任何具有范围的数值类型都存在相同的问题。而且,我也不关心对浮点数损失一点精度数学,因为我只是用它来获取某物的大致上限。
解决方法
在底数R中,使用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
可以很容易地将其编写为函数。
useEffect
,
您可以使用gmp
库。
library(gmp)
factorial(as.bigz(length(x))) / prod(factorial(as.bigz(table(x))))
#[1] 200