limit.h and float.h

teammatt3's picture

He has: 2,102 posts

Joined: Sep 2003

I wrote this program to give me the largest factorial a long int can come up with on my school's system.

#include <stdio.h>
#include <limits.h>
#include <float.h>
int main (void)
{

   unsigned long long int factorial = 1, number = 1, factor = ULONG_MAX;

   while(factorial <= factor && factor > 0)
   {
       factorial = number * factorial;

       printf("%llu     %llu\n", number, factorial);

       number++;
   }


   printf("%u, %u, %u\n"
            "%i, %i, %i", USHRT_MAX, UINT_MAX, ULONG_MAX, FLT_DIG, DBL_DIG, LDBL_DIG);

return 0;
}
'

But the output is

Quote:
1 1
2 2
3 6
4 24
5 120
6 720
7 5040
8 40320
9 362880
10 3628800
11 39916800
12 479001600
13 6227020800
65535, 4294967295, 4294967295
6, 15, 18

What I don't get is this: The ULONG_MAX is 4,294,967,295, but this program calculates upto 6,227,020,800. Why is it calculating a number that is 2 billion higher than the max? Is it because I am defining the vars as unsigned long long int's? But if that was the case, how come it doesn't go all the way to 18446744073709551615?

timjpriebe's picture

He has: 2,667 posts

Joined: Dec 2004

Simple, the loop checks factorial at the beginning, before factorial gets recalculated. So the last time it does the check, factorial is, indeed, less than (or equal to) ULONG_MAX. Then factorial is recalculated, at which point it is then printed, being greater than ULONG_MAX.

If you're just looking to change the output, change

printf("%llu     %llu\n", number, factorial);
'

to

if (factorial <= factor)
{
  printf("%llu     %llu\n", number, factorial);
}
'

teammatt3's picture

He has: 2,102 posts

Joined: Sep 2003

EDIT

Now it should work if I throw it in a for loop like the following, right?

unsigned long long int factorial = 1, number = 1, factor = ULONG_MAX;

for(; factorial <= factor; number++)
{
factorial = number * factorial;

printf("llu        llu\n", number factorial);
}
'

A for loop evaluates the expression before it gives the printf() output, right?. Apparently it doesn't, that gives me the same result (number goes up to 13) (that is without the if in it).

Arggg, I just don't get what is going on...

Tim, the if solves my problem Smiling. It is good enough with my experiments but if it were graded I would get knocked for inefficiency. I asked my professor about it, and his answer totally confused me, which is why I turned to you guys Smiling.

timjpriebe's picture

He has: 2,667 posts

Joined: Dec 2004

The for loop is just evaluating the same thing at the same time. Remember, you're checking the last variable that was put into factorial. The computer has no way of knowing what's ABOUT TO be put in there.

If you want it in the condition, your condition (assuming it's a while loop) should read like this:

while ( (number * factorial <= factor) && (factor > 0) )
'

Does that make sense?

While it's tedious, I sometimes find that if I get a white board (or paper) and calculator out and track each of the variables involved manually through the loop, I can figure out what's going on.

teammatt3's picture

He has: 2,102 posts

Joined: Sep 2003

Quote: While it's tedious, I sometimes find that if I get a white board (or paper) and calculator out and track each of the variables involved manually through the loop, I can figure out what's going on.

Great advice Tim, now it makes perfect sense what's going on in there. Thanks!

timjpriebe's picture

He has: 2,667 posts

Joined: Dec 2004

Not a problem! Sorry I didn't explain it better in my first reply. Laughing out loud

Want to join the discussion? Create an account or log in if you already have one. Joining is fast, free and painless! We’ll even whisk you back here when you’ve finished.