Tom Kuntz
Tom Kuntz

Reputation: 65

Problem to return and printf unsigned long

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.

Upvotes: 0

Views: 347

Answers (1)

Steve Summit
Steve Summit

Reputation: 48053

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.

Upvotes: 1

Related Questions