#include #include // Function declarations int main(); int factorial( int n ); // Function definitions int main() { std::cout << "Starting tests" << std::endl; assert( factorial( 0 ) == 1 ); assert( factorial( 1 ) == 1 ); assert( factorial( 2 ) == 2 ); assert( factorial( 3 ) == 6 ); assert( factorial( 4 ) == 24 ); assert( factorial( 5 ) == 120 ); assert( factorial( 6 ) == 720 ); assert( factorial( 7 ) == 5040 ); assert( factorial( 8 ) == 40320 ); assert( factorial( 9 ) == 362880 ); assert( factorial( 10 ) == 3628800 ); assert( factorial( 11 ) == 39916800 ); assert( factorial( 12 ) == 479001600 ); // On a system with 32-bit integers, 13! cannot be // represented by an int: // // 13! = 6227020800 // // Consequently, the following calculation causes // signed integer overflow, and its result should not // be relied upon. std::cout << "factorial(13) = " << factorial( 13 ) << ", while 13! = 6227020800" << std::endl; std::cout << "Finishing tests" << std::endl; return 0; } // int factorial( ... ) // // @author Douglas Wilhelm Harder // @date 2020-09-09 // @version 1.0 // // @param n a non-negative integer (i.e., 0 or greater) // // @returns n! // // @algorithm // Calculate the product // // 1 * 2 * 3 * ... * (n - 1) * n. // // For n == 0, the loop executes zero times, so the // initial value 1 is returned, giving 0! = 1. // // Exercises: // 1. Is there any reason to start the loop at k == 1? // Could we instead start the loop with // // int k{ 2 } // // and still obtain the same results? // // 2. What happens if the argument is negative? // - Read about the factorial function. // - Is n! defined for negative integers? // - Does this implementation produce an appropriate // result when n < 0? // // 3. This one is more difficult, but interesting. // // After doing some research, you learn that the // factorial function can be extended to most real // numbers using the gamma function: // // x! = Gamma(x + 1). // // It is not defined at the negative integers // // -1, -2, -3, ... // // For this exercise, however, we will construct a // simple approximation without using the standard // library's gamma function. // // For 0 <= x <= 1, approximate x! using the cubic // polynomial // // 3 2 // p(x) = ax + bx + cx + d, // // where // // a = 1 - 2*gamma // b = -1 + 3*gamma // c = -gamma // d = 1 // // and // // gamma = 0.57721566490153286 // // is the Euler-Mascheroni constant. // // Thus, 0.3! is approximated by p(0.3), and // // 6.3! = 6.3*5.3*4.3*3.3*2.3*1.3*0.3! // // can be approximated by replacing 0.3! with // p(0.3). // // You should obtain a value close to 1258.7347. // // Similarly, using // // x! = (x + 1)!/(x + 1), // // we can write // // (-3.7)! = 0.3!/(0.3*(-0.7)*(-1.7)*(-2.7)). // // Replacing 0.3! with p(0.3) should give a value // close to -0.92179052. // // Author an overloaded function // // double factorial( double x ) // // that calculates the appropriate product and then // uses p(x_star), where // // 0 <= x_star <= 1. // // Questions: // - Does your function find a reasonable value for // 13! without the integer-overflow problem above? // - What happens when you try to calculate (-1)!? // - How does this correspond with the definition of // the gamma function? int factorial( int n ) { int result{ 1 }; for ( int k{ 1 }; k <= n; ++k ) { result *= k; } return result; }