对于非常大的数字,近似二项式系数的对数

时间:2019-04-06 19:37:22

标签: c++ c++11 math approximation binomial-coefficients

我目前正努力计算非常大的二项式系数,比如说n <10,000,000且n

到目前为止,我已经尝试了许多方法来处理这些计算所产生的大量数字。但是,问题在于我不需要一次计算这些二项式系数,而是数十万次。这意味着,计算阶乘的常规方法到目前为止太昂贵了,而像long long int这样的标准数据类型太受限制,无法容纳这些数字。

我已经尝试过Boost库中的多精度数据类型,但是正如我提到的那样,进行多次计算会导致性能极慢。我也尝试使用OpenMP进行多线程,但是性能优势仍然太低。结果,我切换到计算二项式系数的对数以使数字保持较小。尽管这解决了很多问题,但是并没有加快处理过程。这就是为什么我尝试了对数二项式系数的斯特林近似。我当前的解决方案如下:

#include <math.h>

long double calc_hgeom(unsigned int k, unsigned int n, unsigned int K, unsigned int N)
{
    long double hprob = std::exp((log_C(K, k) + log_C(N-K, n-k)) - log_C(N, n));
    return hprob;
}

long double log_C(unsigned int u, unsigned int m)
{
    long double C = u * std::log(u) - m * std::log(m) - (u-m) * std::log(u-m)) + 0.5 * (std::log(u) - std::log(m) - std::log(u-m) - std::log(2*M_PI));
    return C;
}

但是,结果与实际值相差很大,最高可达7%。因此,我的问题是:是否有一种有效的方法来计算二项式系数的对数?或者可以改善我的近似值以提高准确性?

任何帮助将不胜感激,因为此计算是我整个算法的基础。

2 个答案:

答案 0 :(得分:1)

考虑R的选择功能...

> choose(10000, 5000) 
[1] Inf
> lchoose(10000, 5000)
[1] 6926.641

R语言的基本源存储库是解决此类问题的重要思路。

请参见https://github.com/wch/r-source/blob/trunk/src/nmath/choose.c

这里的诀窍是使用经过ln转换的输入,以避免溢出。

请注意,该代码已获得GNU许可。

答案 1 :(得分:0)

您应将Sterling's approximation formula用作n! ,应用于二项式系数,可以为您提供:

enter image description here

对于二项式系数本身和对数,

取等式右边的对数;大多数这些东西很快就会变得简单得多。您仍然有k!但是,对于大k来说,您将再次需要近似公式。最终,您将获得更多可行的功能(即,数字更稳定)。

如果这还不够好,也就是说,如果您仍然有一些条款互相抵消,可以考虑在其中一个变量上应用Taylor expansion