You're overflowing your integer type. It's likely that unsigned long long
is 64 bits long for you.
- 20! is
0x21c3_677c_82b4_0000
which fits.
- 21! is
0x2_c507_7d36_b8c4_0000
which does not fit.
You can look into libraries like GMP which enable arbitrarily large integers.
To extend the GMP comment. Here's some code that will calculate the factorial using GMP:
void factorial(unsigned long long n, mpz_t result) {
mpz_set_ui(result, 1);
while (n > 1) {
mpz_mul_ui(result, result, n);
n = n-1;
}
}
int main() {
mpz_t fact;
mpz_init(fact);
factorial(100, fact);
char *as_str = mpz_get_str(NULL, 16, fact);
printf("%s\n", as_str);
mpz_clear(fact);
free(as_str);
}
This will calculate factorial(100)
, and results in:
0x1b30964ec395dc24069528d54bbda40d16e966ef9a70eb21b5b2943a321cdf10391745570cca9420c6ecb3b72ed2ee8b02ea2735c61a000000000000000000000000
And just for fun, here's the C++ version. Constructors, destructors and operator overloading tend to make the C++ version of these things look a bit cleaner. The result is the same as before.
#include <gmpxx.h>
#include <iostream>
int main() {
mpz_class fact = 1;
for (int i=2; i<=100; ++i)
fact *= i;
std::cout << "0x" << fact.get_str(16) << "\n";
}