Saurabh Saxena wrote:
can we calculate the 73! value in c or c++ without loss of
significant digits.
Yes.
c:\c\junk>fact 73
Factorial(73) == 2449473536e16 * pow(3,34) * pow(7,11) * pow(11,6)
* pow(13,5) * pow(17,4) * pow(19,3) * pow(23,3) * pow(29,2) *
pow(31,2) * pow(37,1) * pow(41,1) * pow(43,1) * pow(47,1) *
pow(53,1) * pow(59,1) * pow(61,1) * pow(67,1) * pow(71,1) *
pow(2,29)
/* compute factorials, extended range
on a 32 bit machine this can reach fact(15) without
unusual output formats. With the prime table shown
overflow occurs at 101.
Public domain, by C.B. Falconer.
*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
/* 2 and 5 are handled separately
Placing 2 at the end attempts to preserve such factors
for use with the 5 factor and exponential notation
*/
static unsigned char primes[] = {3,7,11,13,17,1 9,23,29,31,37,
41,43,47,53,57, 59,61,67,71,
/* add further primes here -->*/
2,5,0};
static unsigned int primect[sizeof primes]; /* = {0} */
static
unsigned long int fact(unsigned int n, unsigned int *zeroes)
{
unsigned long val;
unsigned int i, j, k;
#define OFLOW ((ULONG_MAX / j) < val)
/* This is a crude mechanism for passing back values */
for (i = 0; i < sizeof primes; i++) primect[i] = 0;
for (i = 1, val = 1UL, *zeroes = 0; i <= n; i++) {
j = i;
/* extract exponent of 10 */
while ((0 == (j % 5)) && (!(val & 1))) {
j /= 5; val /= 2;
(*zeroes)++;
}
/* Now try to avoid any overflows */
k = 0;
while (primes[k] && OFLOW) {
/* remove factors primes[k] */
while (0 == (val % primes[k]) && OFLOW) {
val /= primes[k];
++primect[k];
}
while (0 == (j % primes[k]) && OFLOW) {
j /= primes[k];
++primect[k];
}
k++;
}
/* Did we succeed in the avoidance */
if (OFLOW) {
#if DEBUG
fprintf(stderr, "Overflow at %u, %lue%u * %u\n",
i, val, *zeroes, j);
#endif
val = 0;
break;
}
val *= j;
}
return val;
} /* fact */
int main(int argc, char *argv[])
{
unsigned int x, zeroes;
unsigned long f;
if ((2 == argc) && (1 == sscanf(argv[1], "%u", &x))) {
if (!(f = fact(x, &zeroes))) {
fputs("Overflow \n", stderr);
return EXIT_FAILURE;
}
printf("Factori al(%u) == %lu", x, f);
if (zeroes) printf("e%u", zeroes);
for (x = 0; primes[x]; x++) {
if (primect[x]) {
printf(" * pow(%d,%d)", primes[x], primect[x]);
}
}
putchar('\n');
return 0;
}
fputs("Usage: fact n\n", stderr);
return EXIT_FAILURE;
} /* main */
--
Chuck F (cb********@yah oo.com) (cb********@wor ldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net> USE worldnet address!