0

I don't understand why my code is still printing int values (that are overflown) while I want unsigned long values!

There is my code :

#include <stdio.h>

unsigned long factorial(int num) {
    if ((num == 0) || (num == 1 )) {
        return 1;
    } else if (num < 0) {
        return 0;
    } else {
        return num * factorial(num - 1);
    }
}

int main(void) {
    int num;
    char liste;
    printf("Choisir un nombre pour trouver son factoriel : ");
    //Translation : "Choose a number to find its factorial" 
    scanf("%d", &num);
    printf("factoriel de %d : %lu\n", num, factorial(num));
}

It is a very basic code to return factorial value but I'm just a beginner.

Mat
  • 202,337
  • 40
  • 393
  • 406
Tom Kuntz
  • 55
  • 1
  • 7
  • 1
    Can you provide examples of input (and corresponding output) that demonstrates the problem? – Scott Hunter Jul 06 '21 at 18:58
  • 4
    Please state what your input is, what output you are expecting and what you are actually getting. – Eugene Sh. Jul 06 '21 at 18:58
  • You're declared `factorial` to return `unsigned long` but everything else in both that function and `main` deals in `int`. – Chris Jul 06 '21 at 19:02
  • If type `long` on your machine is 32 bits, it won't make a difference whether you use signed or unsigned; you're still going to get overflow. 12! needs 29 bits and will work with either a signed or an unsigned 32-bit type. 13! needs 33 bits and will therefore typically need a 64-bit type, perhaps `long long`. – Steve Summit Jul 06 '21 at 19:03
  • Works fine here https://godbolt.org/z/G38oKxcn3 – Edgen Jul 06 '21 at 19:04
  • @ChrisDutton I believe he's got just enough declared as `unsigned long` for it to work, *if* `unsigned long` is a 64-bit type. – Steve Summit Jul 06 '21 at 19:05
  • Assuming a `long` is 64 bit, anything larger than 21! won't fit. – dbush Jul 06 '21 at 19:05
  • If you're using Windows it's very likely your `int` is 4 bytes, as @Steve advised use `long long` or `uint64_t`, I would use the latter, it does not deppend on the system, the size is always 8 bytes. – anastaciu Jul 06 '21 at 19:15
  • 2
    Edit the question to provide a [mre], including an input for which the program fails, the observed output, and the output expected instead (or at least a description that distinguishes it from the observed output). This sample will likely clarify whether your program is failing because `unsigned long` is only 32 bits in your C implementation or because your input produces a factorial too large for even 64-bit numbers. – Eric Postpischil Jul 06 '21 at 19:32

1 Answers1

1

The factorial function grows very fast. Just about no matter what type you use for your computations, it's going to overflow pretty soon.

On a machine where type unsigned long has 32 bits (which is all that's guaranteed), your program can correctly compute 12! = 479001600 (but nothing larger). I suspect that's what you're seeing.

On a machine where type unsigned long has 64 bits, your program can correctly compute 20! = 2432902008176640000. (My machine has 64-bit longs, and I used your program to compute this result, and it worked fine.)

So your program is actually fine; I can't see anything wrong with it. (Well, there's an unused variable liste, and a stray loaf of bread in a comment. :-) )

If your compiler and C library both support type long long, you can try this to increase the range on your machine:

#include <stdio.h>

unsigned long long factorial(int num) {
    if (num < 0) {
        return 0;
    } else if (num <= 1 ) {
        return num;
    } else {
        return num * factorial(num - 1);
    }
}

int main(void) {
    int num;
    printf("Choisir un nombre pour trouver son factoriel : ");
    scanf("%d", &num);
    printf("factoriel de %d : %llu\n", num, factorial(num));
}

But, again, this'll only get you up to 20!. (In this version I have also cleaned up the logic of your factorial function slightly.)

If %llu doesn't work, you can try %Lu.

Some compilers support a 128-bit type (I think gcc calls it _uint128_t or something like that), and this could theoretically get you up to 34! = 295232799039604140847618609643520000000.

But beyond that you'd have to use a "multiple precision" or "arbitrary precision" library such as GMP. For example, 100! has 525 bits, and 1000! has 8530 bits.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103