The formula P(n) = (n!)(6^n) in C produces a large value

327 views Asked by At

I'm trying to represent the following mathematical expression in C:

P(n) = (n!)(6^n)

The program should compute the answer to expression when n = 156. I have attempted to create the program in C and it fails to produce an answer. The answer is approximately 10^397. The program utilises 2 logarithmic identities. It also utilises Stirling's approximation to calculate the large factorial.

How can I make it produce the correct answer and do you have any suggestions as to how I could improve the code? (I'm fairly new to programming):

#include <math.h>
typedef unsigned int uint;

int main()
{
uint n=156;                               // Declare variables
double F,pi=3.14159265359,L,e=exp(1),P;
F = sqrt(2*pi*n) * pow((n/e),n);          // Stirling's Approximation Formula
L = log(F) + n*log(6);                    // Transform P(n) using logarithms - log(xy) = log(x) + log(y) and log(y^n) = n*log(y)
P = pow(e,L);                             // Transform the resultant logarithm back to a normal numbers
}

Thank you! :)

4

There are 4 answers

4
SpikeMF On

Loosely speaking, in C a double is represented as a base number raised to a power. As already mentioned, the maximum is roughly 1E308, but as you get to larger and larger numbers (or smaller and smaller), you lose precision because the base number has a finite number of digits and cannot always be accurately represented in this way.

See http://en.wikipedia.org/wiki/Double-precision_floating-point_format for more information

8
Russell Borogove On

Neither integer nor floating point variables in most C implementations can support numbers of that magnitude. Typical 64-bit doubles go up to something like 10308 with substantial loss of precision at that magnitude.

You'll need what's called a 'bignum library' to compute this, which is not part of standard C.

11
Fred Larson On

One idea is to use the long double type. Its precision isn't guaranteed, so it may or may not be big enough for your needs, depending on what compiler you're using.

Replace double with long double. Add an 'l' (lower case L) suffix to all math functions (expl, logl, powl, sqrtl). Compile with C99 enabled, since the long double math functions are provided in C99. It worked for me using GCC 4.8.1.

#include <math.h>
#include <stdio.h>
typedef unsigned int uint;

int main()
{
    uint n=156;                               // Declare variables
    long double F,pi=3.14159265359,L,e=expl(1),P;
    F = sqrtl(2*pi*n) * powl((n/e),n);          // Stirling's Approximation Formula
    L = logl(F) + n*logl(6);                    // Transform P(n) using logarithms - log(xy) = log(x) + log(y) and log(y^n) = n*log(y)
    P = powl(e,L);                             // Transform the resultant logarithm back to a normal numbers
    printf("%Lg\n", P);
}

I get 1.83969e+397.

0
thelastpanda On
#include <math.h>
#include <float.h>
typedef unsigned int uint;

int main()
{
uint n=156;                               // Declare variables
long double F,pi=3.14159265359,L,e=expl(1),P;
F = sqrtl(2*pi*n) * powl((n/e),n);          // Stirling's Approximation Formula
L = logl(F) + n*logl(6);                    // Transform P(n) using logarithms - log(xy) = log(x) + log(y) and log(y^n) = n*log(y)
P = powl(e,L);                             // Transform the resultant logarithm back to a normal numbers
printf("%d\n", LDBL_MAX_10_EXP);
}