Search code examples
c++factorial

Factorial Function giving negative no


So I have written a program in c++ which was suppose to print factorials of number from 1 endlessly. It printed the first some number as expected with correct factorial value but after that it is just end up getting negative value and Program got terminated due to condition mentioned. But I am not sure how a good working factorial program end up getting negative value.

#include<iostream>
using namespace std;
int main(){
    int a = 1;
    int c = 1;
    while(a>0){
        cout<<(a*c)<<endl;
       
        a = a*c;
        c = c+1;
    }
    return 0;
}

I have Expected Endless result of factorial from 1 to forever.

Result I got-

1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
1932053504
1278945280
2004310016
2004189184 //Number Decreased Instead of Increasing
-288522240 //Now It is negative

Solution

  • int is a signed type. Your factorials gets big enough to overflow that (exceed the largest value an int can store. When they do, you start to see answers that don't seem to make sense.

    This can be readily seen with a simple demo program:

    $ cat test.cpp
    #include <iostream>
    #include <iomanip>
    #include <limits.h>
    
    int factorial(int n) {
        int result = 1;
        for (; n > 1; n--) result *= n;
        return result;
    }
    
    int main() {
        for (int i = 1; i < 20; i++) {
            std::cout << std::setw(10) << std::right
                      << factorial(i) << std::endl
                      << INT_MAX << " <- max " << std::endl;
        }
    }
    $ g++ test.cpp
    $ ./a.out
             1
    2147483647 <- max
             2
    2147483647 <- max
             6
    2147483647 <- max
            24
    2147483647 <- max
           120
    2147483647 <- max
           720
    2147483647 <- max
          5040
    2147483647 <- max
         40320
    2147483647 <- max
        362880
    2147483647 <- max
       3628800
    2147483647 <- max
      39916800
    2147483647 <- max
     479001600
    2147483647 <- max
    1932053504
    2147483647 <- max
    1278945280
    2147483647 <- max
    2004310016
    2147483647 <- max
    2004189184
    2147483647 <- max
    -288522240
    2147483647 <- max
    -898433024
    2147483647 <- max
     109641728
    2147483647 <- max
    

    If you want to see larger factorial results, you need to use a larger integer type, and likely a larger unsigned integer type.

    If we do this, we buy ourselves some additional space to generate larger factorials.

    $ cat test.cpp
    #include <iostream>
    #include <iomanip>
    
    unsigned long long int factorial(int n) {
        unsigned long long int result = 1;
        for (; n > 1; n--) result *= n;
        return result;
    }
    
    int main() {
        for (int i = 1; i < 20; i++) {
            std::cout << std::setw(19) << std::right
                      << factorial(i) << std::endl
                      << ULONG_LONG_MAX << " <- max " << std::endl;
        }
    }
    $ g++ test.cpp
    $ ./a.out
                      1
    9223372036854775807 <- max
                      2
    9223372036854775807 <- max
                      6
    9223372036854775807 <- max
                     24
    9223372036854775807 <- max
                    120
    9223372036854775807 <- max
                    720
    9223372036854775807 <- max
                   5040
    9223372036854775807 <- max
                  40320
    9223372036854775807 <- max
                 362880
    9223372036854775807 <- max
                3628800
    9223372036854775807 <- max
               39916800
    9223372036854775807 <- max
              479001600
    9223372036854775807 <- max
             6227020800
    9223372036854775807 <- max
            87178291200
    9223372036854775807 <- max
          1307674368000
    9223372036854775807 <- max
         20922789888000
    9223372036854775807 <- max
        355687428096000
    9223372036854775807 <- max
       6402373705728000
    9223372036854775807 <- max
     121645100408832000
    9223372036854775807 <- max