I’m doing a program that calculates the probability of lotteries.
Specification is choose 5 numbers out of 47 and 1 out of 27
So I did the following:
#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;
}
However the program doesn’t work. The program calculates for 30 seconds, then gives me Process 4 exited with code -1,073,741,676 I have to change all the long int to long double, but that loses precision. Is it because long int is too short for the big values? Though I thought long int nowadays are 64bit? My compiler is g++ win32 (64bit host).
Whether
longis 64-bit or not depends on the model. Windows uses a 32-bitlong. Useint64_tfrom<stdint.h>if you need to ensure it is 64-bit.But even if
longis 64-bit it is still too small to holdfactorial(47).although 47C5 is way smaller than that.
You should never use nCr == n!/(r! (n-r)!) directly do the calculation as it overflows easily. Instead, factor out the n!/(n-r)! to get:
this can be managed even by a 32-bit integer.
BTW, for @Coffee’s question: a
doubleonly has 53-bits of precision, where 47! requires 154 bits. 47! and 42! represented indoublewould beso 47! / (42! × 5!)’s possible range of value will be
that’s enough to get the exact value 47C5.