add a way of calculate factorials of large numbers

This commit is contained in:
Tiago Gomes 2012-04-17 20:24:40 +01:00
parent f02d0fb798
commit cd8714460e
3 changed files with 52 additions and 16 deletions

View File

@ -44,7 +44,7 @@ HistogramSet::operator[] (unsigned idx) const
unsigned unsigned
HistogramSet::nrHistograms (void) const HistogramSet::nrHistograms (void) const
{ {
return Util::nrCombinations (size_ + hist_.size() - 1, hist_.size() - 1); return Util::multichoose (size_, hist_.size());
} }
@ -77,7 +77,7 @@ HistogramSet::getHistograms (unsigned N, unsigned R)
unsigned unsigned
HistogramSet::nrHistograms (unsigned N, unsigned R) HistogramSet::nrHistograms (unsigned N, unsigned R)
{ {
return Util::nrCombinations (N + R - 1, R - 1); return Util::multichoose (N, R);
} }

View File

@ -69,10 +69,10 @@ fromLog (Params& v)
double double
factorial (double num) factorial (unsigned num)
{ {
double result = 1.0; double result = 1.0;
for (int i = 1; i <= num; i++) { for (unsigned i = 1; i <= num; i++) {
result *= i; result *= i;
} }
return result; return result;
@ -80,15 +80,47 @@ factorial (double num)
unsigned double
nrCombinations (unsigned n, unsigned r) logFactorial (unsigned num)
{ {
assert (n >= r); double result = 0.0;
unsigned prod = 1; for (unsigned i = 1; i <= num; i++) {
for (int i = (int)n; i > (int)(n - r); i--) { result += std::log (i);
prod *= i;
} }
return (prod / factorial (r)); return result;
}
unsigned
choose (unsigned n, unsigned k)
{
assert (n >= k);
int diff = n - k;
unsigned result = 0;
if (n < 150) {
unsigned prod = 1;
for (int i = n; i > diff; i--) {
prod *= i;
}
result = prod / factorial (k);
} else {
double prod = 0.0;
for (int i = n; i > diff; i--) {
prod += std::log (i);
}
prod -= logFactorial (k);
result = static_cast<unsigned> (std::exp (prod));
}
return result;
}
unsigned
multichoose (unsigned n, unsigned k)
{
return choose (n + k - 1, k);
} }
@ -106,11 +138,11 @@ expectedSize (const Ranges& ranges)
unsigned unsigned
getNumberOfDigits (int number) getNumberOfDigits (int num)
{ {
unsigned count = 1; unsigned count = 1;
while (number >= 10) { while (num >= 10) {
number /= 10; num /= 10;
count ++; count ++;
} }
return count; return count;

View File

@ -52,9 +52,13 @@ void add (Params&, const Params&);
void add (Params&, const Params&, unsigned); void add (Params&, const Params&, unsigned);
double factorial (double); double factorial (unsigned);
unsigned nrCombinations (unsigned, unsigned); double logFactorial (unsigned);
unsigned choose (unsigned, unsigned);
unsigned multichoose (unsigned, unsigned);
unsigned expectedSize (const Ranges&); unsigned expectedSize (const Ranges&);