Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can anyone explain this algorithm for calculating large factorials?

Tags:

i came across the following program for calculating large factorials(numbers as big as 100).. can anyone explain me the basic idea used in this algorithm?? I need to know just the mathematics implemented in calculating the factorial.

#include <cmath> #include <iostream> #include <cstdlib>  using namespace std;  int main() {        unsigned int d;        unsigned char *a;        unsigned int j, n, q, z, t;        int i,arr[101],f;        double p;       cin>>n;     p = 0.0;     for(j = 2; j <= n; j++)         p += log10(j);     d = (int)p + 1;     a = new unsigned char[d];     for (i = 1; i < d; i++)         a[i] = 0; //initialize     a[0] = 1;     p = 0.0;     for (j = 2; j <= n; j++)     {         q = 0;         p += log10(j);         z = (int)p + 1;         for (i = 0; i <= z/*NUMDIGITS*/; i++)         {             t = (a[i] * j) + q;             q = (t / 10);             a[i] = (char)(t % 10);         }      }     for( i = d -1; i >= 0; i--)         cout << (int)a[i];     cout<<"\n";     delete []a;  return 0; } 
like image 528
Vaibhav Avatar asked Jan 24 '10 15:01

Vaibhav


People also ask

How do you calculate factorial algorithm?

Algorithm of Factorial Program in C Read the integer and assign it to a variable. From the value of the integer up to 1, multiply each digit and update the final value. The final value at the end of all the multiplication till 1 is the factorial.

Which of the following can be used to evaluate the factorial of a large number?

Using "BigInteger" we can calculate Factorial of large numbers easily . We can even calculate factorial of 10000 easily ....


1 Answers

Note that

n! = 2 * 3 * ... * n 

so that

log(n!) = log(2 * 3 * ... * n) = log(2) + log(3) + ... + log(n) 

This is important because if k is a positive integer then the ceiling of log(k) is the number of digits in the base-10 representation of k. Thus, these lines of code are counting the number of digits in n!.

p = 0.0; for(j = 2; j <= n; j++)     p += log10(j); d = (int)p + 1; 

Then, these lines of code allocate space to hold the digits of n!:

a = new unsigned char[d]; for (i = 1; i < d; i++)     a[i] = 0; //initialize 

Then we just do the grade-school multiplication algorithm

p = 0.0; for (j = 2; j <= n; j++) {     q = 0;     p += log10(j);     z = (int)p + 1;     for (i = 0; i <= z/*NUMDIGITS*/; i++) {         t = (a[i] * j) + q;         q = (t / 10);         a[i] = (char)(t % 10);     } } 

The outer loop is running from j from 2 to n because at each step we will multiply the current result represented by the digits in a by j. The inner loop is the grade-school multiplication algorithm wherein we multiply each digit by j and carry the result into q if necessary.

The p = 0.0 before the nested loop and the p += log10(j) inside the loop just keep track of the number of digits in the answer so far.

Incidentally, I think there is a bug in this part of the program. The loop condition should be i < z not i <= z otherwise we will be writing past the end of a when z == d which will happen for sure when j == n. Thus replace

for (i = 0; i <= z/*NUMDIGITS*/; i++) 

by

for (i = 0; i < z/*NUMDIGITS*/; i++) 

Then we just print out the digits

for( i = d -1; i >= 0; i--)     cout << (int)a[i]; cout<<"\n"; 

and free the allocated memory

delete []a; 
like image 129
jason Avatar answered Oct 21 '22 04:10

jason