1

I'm trying to calculate 52! using C language. But it seems that somehow, I can't handle big numbers. I can't telle if it's my compiler or if I'm doing it wrong..

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

uint64_t factorielle(int n) {
   if(n == 0)
       return 1;
    else
      return n * factorielle(n-1);
}

int main(int argn, char** argv) {

  printf("Number : %"PRId64"\n", factorielle(52));

  return 0;
}

I get this result :

Number : -8452693550620999680

I tryed with GCC 5.3.0, GCC 7.2.0 and Zapcc 5.0.0

Thanks a lot !

  • 4
    It's worth doing some research on the range of values that will fit into an `int`. – Oliver Charlesworth Nov 27 '17 at 10:41
  • 1
    You can't calculate factorial of numbers greater than 21! on 64 bit machine by this method. – haccks Nov 27 '17 at 10:42
  • You have mismatching format and argument type when printing the result. You tell `printf` to print a *signed* value, but `factorielle` returns an *unsigned* value. Fixing this won't help though, for that you need a *bignum library*. – Some programmer dude Nov 27 '17 at 10:43
  • 52! = 8.0658175e+67 >(is far more supperior)> 2^64-1 = 1.8446744e+19 – Julien Nov 27 '17 at 10:46
  • 2
    Generally: each time you write or think something like _I can't tell if it's my compiler or if I'm doing it wrong_, __you__ are doing something wrong. – Jabberwocky Nov 27 '17 at 10:46
  • Trying to find permutation combinations of card game? – Vagish Nov 27 '17 at 10:49
  • Try to use `PRIu64` instead of `PRId64`. Your function returns an unsigned integer! But I think 52! generate a number too big! – Sir Jo Black Nov 27 '17 at 10:49
  • This gets asked from time to time (see duplicate) and well, builtin datatypes **do** have some limitations. Just for fun, I came up [with this implementation](https://github.com/Zirias/hugeint/blob/master/src/factorial/factorial.c) a while ago. –  Nov 27 '17 at 10:52
  • Thanks a lot everyone, I'll figure this out ! –  Nov 27 '17 at 10:53
  • The bigger number you may represent with an `uint64_t` is, obviously, 0xFFFFFFFFFFFFFFFF that is 18.446.744.073.709.551.615! – Sir Jo Black Nov 27 '17 at 10:53
  • 2
    @SergioFormiggini especially in the context of this question, `18.446.744.073.709.551.615!` (!) seems a bit large... ;) –  Nov 27 '17 at 10:59
  • @FelixPalmen, Why do you think it's a bit large!? I printed the result using: `uint64_t x = (0xFFFFFFFFFFFFFFFF); printf("Number : %"PRIu64"\n", x);` ... ;) – Sir Jo Black Nov 27 '17 at 11:01
  • 52! is 8,0658175170943878571660636856404e+67 ... e+67 is a bit larger then 18.446.744.073.709.551.615 (1,8 e+19). – Sir Jo Black Nov 27 '17 at 11:04
  • @FelixPalmen , yes (excuse me) in the context the max 64 bit integer is a bit small of 52! ... ;) – Sir Jo Black Nov 27 '17 at 11:05
  • Ah ah ah ah ... @FelixPalmen, I didn't realize I've written "18.446.744.073.709.551.615!" ... XD – Sir Jo Black Nov 27 '17 at 11:17

3 Answers3

3

You can never represent 52! in any of the C integer types (64 bit). One solution is to use your own data structure to represent that big a value or try to find some library (such as GMP which provides that facility.

You can check that the value of 2^64 itself is 1.8446744e+19 which is far smaller than 8.0658175e+67. So there's no way possible using integer types in C.

Some more thoughts into You can never represent 52! in any of the C integer types

As it is being mentioned, it is not possible for many of the system which use 64 bit integer types (int64_t). Let's delve into the matter. (54! requires 238 binary units). With a type of int256_t, it is would be possible to represent 52!. But int256_t is not a standard type as of now. The DEC VAX even supported operations on 128-bit integer. As mentioned by chux even now various compilers support 128 bit integer types and operations, so it is not an impossible feat to extend it to support the 256 bit integer types. Then I guess it couldn't be said You can never represent 52! in any of the C integer types

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user2736738
  • 30,591
  • 5
  • 42
  • 56
  • Ok I will try using a better data structure. I'll figure this out. Thanks ! –  Nov 27 '17 at 10:50
  • "You can never represent 52! in any of the C integer types." --> 54! needs about 238 binary bits. A type like `int256_t` can handle that. Although `int256_t` is not a standard type, "never" is a long time. Even now various compilers offer 128-bit integer types and a compiler today _could_ support such wide 128/256 bit types. A 256 bit integer is not that far-fetched. Maybe in a decade or two. – chux - Reinstate Monica Nov 27 '17 at 15:29
  • @chux.: That's a nice thought. In fact I thought that when writing. The way it;s changing that might to be that far. Once again thanks for the input. I will edit..and ask for a look up if you don't mind. – user2736738 Nov 27 '17 at 15:31
3

Read more about factorials.

Hint: it is always useful to read a little bit before coding if you are not familiar with the subject.

Try to find out an estimate of the factorial of 52 (e.g. of its logarithm). For that purpose, you might use Stirling's approximation. You'll discover that it is really a big number (much bigger than 264-1, which is generally the largest number your C implementation can handle).

Consider using some arbitrary precision arithmetic (a.k.a. "bignum"s) library such as GMPlib. BTW, efficient bignum libraries are really difficult to code (so you'll do much worse than what existing libraries give you) because their algorithmics is very difficult.

Perhaps you don't need to compute such a big factorial.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Ok thanks a lot. I didn't know anything about that. I will do some research. –  Nov 27 '17 at 10:48
  • 1
    For smallish numbers, e.g. 52, you can calculate the log of n! using the math library function lgamma(). Converting this natural log to a base2 log will give yous an estimate of how many bits you'll need. In this case, lgamma(53.0)/log(2.0) gives 2.255810031e+02 so you'll need 226 bits. – dmuir Nov 27 '17 at 14:15
2

Factorial of 54 is

230843697339241380472092742683027581083278564571807941132288000000000000

which is too big to handle by any primitive data types in C.

If you are trying to implement a factorial program to calculate factorials of such big numbers then you can follow this tutorial.

haccks
  • 104,019
  • 25
  • 176
  • 264
  • I will check this tutorial, thanks. I wasn't really looking for the value itself, but I wanted to figure this problem out for personnal knowledge. –  Nov 27 '17 at 10:51