[英]How to calculate large numbers in c++ (large factorials and powers)
我想計算投擲 234 個骰子時得到 40 個或更少 3 的概率。 所以我使用二項分布,它使用大冪(在這種情況下高達 40)和大階乘(在這種情況下高達 234): 在計算這些大數時我得到這個錯誤:
“浮點異常(核心轉儲)”
有什么方法可以修復此錯誤並正確計算,因為 double 甚至 long double 都不足以表示 (1/6)^40 或 (234?)?
我的代碼:
int factorial(int n)
{
if(n == 0 or n == 1)
{
return 1;
}
else
{
return n * factorial(n - 1);
}
}
double binomialDensity(int n, int k, double p)
{
return (factorial(n) / (factorial(k) * factorial(n-k)) * pow(p, k) * pow((1 - p), (n-k)));
}
int main()
{
long double probability;
for(int i = 0; i <= 40; i++)
{
probability += binomialDensity(234, i, 1/6);
}
cout << probability << endl;
return 0;
}
數值編程就是要避免產生大量數字的技術,尤其是當它們在計算過程中取消時。
這里使用帕斯卡三角形是更好的方法。
如果您擔心這種方法的運行時性能,請使用元編程、 constexpr
編程等對其進行編程。 &C。
您不需要如此大的中間結果。 考慮例如
factorial(n) / factorial(k) == (k+1) * (k+2) * .... * n
右側的量級比左側的各個項小得多。
您使用的公式對數學很有用,因為它可讀性強且便於分析。 要計算結果,您應該使用其他東西。 以下是使用循環累加最終結果。 它當然不是數值上最穩定的,但它應該解釋這個想法:
#include <cmath>
#include <iostream>
int factorial(int n)
{
if(n == 0 or n == 1)
{
return 1;
}
else
{
return n * factorial(n - 1);
}
}
double binomialDensity(int n, int k, double p)
{
return (factorial(n) / (factorial(k) * factorial(n-k)) * pow(p, k) * pow((1 - p), (n-k)));
}
double binomialDensity2(int n,int k, double p) {
double result = 1;
for (int i = k+1; i <= n; ++i) result *= i; // factorial(n) / factorial(k)
for (int i = 1; i <= n-k;++i) result /= i; // factorial(n-k)
for (int i = 0; i < k; ++i) result *=p; // pow(p,k)
for (int i = 0; i < n-k; ++i) result *=(1-p); // pow(p-1,n-k)
return result;
}
int main() {
int n = 10;
double p = 0.5;
for (int k=1; k < n; ++k){
std::cout << binomialDensity(n,k,p) - binomialDensity2(n,k,p) << "\n";
}
}
main
將您的解決方案與在您的解決方案仍然有效的范圍內使用循環的解決方案進行比較。 binomialDensity2
仍然使用相對較大的中間結果。 為了清楚起見,可以通過組合我在此處分開的循環來緩解這種情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.