【发布时间】:2019-08-28 09:12:40
【问题描述】:
我目前正在努力计算非常大的数字的二项式系数,假设 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 %。因此我的问题是:是否有一种有效的方法来计算二项式系数的对数,或者我的近似值是否可以改进以提高准确性?
任何帮助将不胜感激,因为这个计算是我整个算法的基础。
【问题讨论】:
-
您是否尝试为 en.wikipedia.org/wiki/… 的第三个公式中给出的斯特林公式添加第一(两个)校正项?这与后面的近似部分中的其他公式相比如何?
-
@LutzL:感谢您的快速回复。我一定会测试您提到的其他更正条款并比较准确性。
-
这很奇怪。查看 Wiki 文章中的相对错误图表,7% 应该通过
n=100。所以对于n = 1e7,第一个近似值应该要好得多
标签: c++ c++11 math approximation binomial-coefficients