fork download
  1. // Factorial. (2.01)
  2.  
  3. #include <limits.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7.  
  8. // Utility.
  9.  
  10. _Bool sign_different_p(int a, int b)
  11. {
  12. return (a ^ b) < 0;
  13. }
  14.  
  15. _Bool mul_overflow_p(int a, int b)
  16. {
  17. if (a == 0 || b == 0)
  18. return 0;
  19. if (sign_different_p(a, b))
  20. return (a < 0) ? INT_MIN/b > a : INT_MIN/a > b;
  21. else
  22. return (a < 0) ? INT_MAX/a > b : INT_MAX/a < b;
  23. }
  24.  
  25. _Bool mul_overflow(int a, int b, int *result)
  26. {
  27. if (mul_overflow_p(a, b))
  28. return 1;
  29. *result = a * b;
  30. return 0;
  31. }
  32.  
  33. // Main.
  34.  
  35. int factorial(int n)
  36. {
  37. if (n < 0)
  38. {
  39. errno = EDOM;
  40. return -1;
  41. }
  42.  
  43. int result = 1;
  44.  
  45. while (n > 1)
  46. {
  47. if (mul_overflow(n, result, &result))
  48. {
  49. errno = ERANGE;
  50. return -1;
  51. }
  52. n -= 1;
  53. }
  54. return result;
  55. }
  56.  
  57. int main(void)
  58. {
  59. for (int i = -1; i < 14; i++)
  60. {
  61. int result = factorial(i);
  62. if (result < 0)
  63. printf("%2d! : %s\n", i, strerror(errno));
  64. else
  65. printf("%2d! : %d\n", i, result);
  66. }
  67. return 0;
  68. }
Success #stdin #stdout 0s 5316KB
stdin
Standard input is empty
stdout
-1! : Numerical argument out of domain
 0! : 1
 1! : 1
 2! : 2
 3! : 6
 4! : 24
 5! : 120
 6! : 720
 7! : 5040
 8! : 40320
 9! : 362880
10! : 3628800
11! : 39916800
12! : 479001600
13! : Numerical result out of range