我正在做一个计算彩票概率的程序。 规范是选择47个中的5个数字和27个中的1个
所以我做了以下事情:
#include <iostream>
long int choose(unsigned n, unsigned k);
long int factorial(unsigned n);
int main(){
using namespace std;
long int regularProb, megaProb;
regularProb = choose(47, 5);
megaProb = choose(27, 1);
cout << "The probability of the correct number is 1 out of " << (regularProb * megaProb) << endl;
return 0;
}
long int choose(unsigned n, unsigned k){
return factorial(n) / (factorial(k) * factorial(n-k));
}
long int factorial(unsigned n){
long int result = 1;
for (int i=2;i<=n;i++) result *= i;
return result;
}
但是该程序不起作用。程序计算30秒,然后给我Process 4 exited with code -1,073,741,676
我必须将所有long int更改为long double,但这会失去精度。是因为long int对于大值来说太短了吗?虽然我认为现在的长篇是64位?我的编译器是g ++ win32(64位主机)。
答案 0 :(得分:18)
long
是否为64位取决于模型。 Windows uses a 32-bit long
。如果您需要确保它是64位,请使用int64_t
from <stdint.h>
。
但即使long
为64位,它仍然太小而无法容纳factorial(47)
。
47! == 2.58623242e+59
2^64 == 1.84467441e+19
虽然 47 C 5 比这个小。
你永远不应该使用 n C r == n!/(r!(n-r)!)直接进行计算,因为它很容易溢出。取而代之的是n!/(n-r)!到get:
47 * 46 * 45 * 44 * 43
C = ----------------------
47 5 5 * 4 * 3 * 2 * 1
这甚至可以通过32位整数进行管理。
BTW,对于@ Coffee的问题:double
只有53位的精度,其中47!需要154位。 47!和42!在double
中表示的将是
47! = (0b10100100110011011110001010000100011110111001100100100 << 145) ± (1 << 144)
42! = (0b11110000010101100000011101010010010001101100101001000 << 117) ± (1 << 116)
所以47! /(42!×5!)的可能值范围
0b101110110011111110011 = 1533939 53 bits
v
max = 0b101110110011111110011.000000000000000000000000000000001001111...
val = 0b101110110011111110010.111111111111111111111111111111111010100...
min = 0b101110110011111110010.111111111111111111111111111111101011010...
这足以得到准确的值 47 C 5 。
答案 1 :(得分:3)
要使用64位长,您应该使用long long
。 (as mentioned here)
答案 2 :(得分:0)
KennyTM说得对,无论你使用什么类型,你都会溢出。您需要更聪明地处理问题并分解大量工作。如果你对一个近似的答案没问题,那么看看斯特林的近似值:
Ln(n!) ~ n Ln(n) - n
所以,如果你有
n!/(k!*(n-k)!)
你可以说那是
e(ln(n!/(k!*(n-k)!)))
经过一些数学考试(仔细检查以确保我做对了)
e(n*ln(n)-k*ln(k)-(n-k)*ln(n-k))
那不应该溢出(但这是一个近似的答案)
答案 3 :(得分:0)
使用标准unsigned long
32位算法,很容易计算高达47C5及以上的二项式系数而不会溢出。请参阅我对此问题的回复:https://math.stackexchange.com/questions/34518/are-there-examples-where-mathematicians-needs-to-calculate-big-combinations/34530#comment-76389