#include #include #include #include // Function declarations int main(); double my_sin( double x ); // Function definitions int main() { std::cout << my_sin( 0.5 ) << std::endl; std::cout << std::sin( 0.5 ) << std::endl; // Uncommenting either of these should cause an // assertion failure because the argument is outside // the interval [0, pi/2]. // // std::cout << my_sin( 1.6 ) << std::endl; // std::cout << my_sin( -0.3 ) << std::endl; return 0; } // double my_sin( ... ) // // @author Douglas Wilhelm Harder // @date 2020-09-09 // @version 1.1 // // @param x a real number 'x' where 0 <= x <= pi/2 // // @returns an approximation of sin(x) // // @algorithm // Evaluate the cubic polynomial // // 3 2 // p(x) = ax + bx + cx + d. // // The coefficients are found by requiring that the // polynomial agree with sin(x) and its derivative at // the two endpoints: // // 1. p(0) = 0 and therefore d = 0, // 2. p'(0) = 1 and therefore c = 1, // 3. p(pi/2) = 1, // 4. p'(pi/2) = 0. // // Substituting c = 1 and d = 0 into the last two // equations gives // // 3 2 // pi a + 2 pi b = 8 - 4 pi // // and // // 2 // 3 pi a + 4 pi b = -4. // // Solving these equations gives // // 4 16 // a = --- - -----, // 2 3 // pi pi // // 4 3 // b = - -- + ---, // pi 2 // pi // // c = 1, // // d = 0. // // This cubic approximation is intended for the interval // [0, pi/2], so an assertion is used to require that the // argument lie within these bounds. // // Exercise: // What would happen if you accidentally wrote // // assert( // (x >= 0.0) || // (x <= std::numbers::pi/2.0) // ); // // instead of // // assert( // (x >= 0.0) && // (x <= std::numbers::pi/2.0) // ); // // For which finite values of 'x' would the incorrect // assertion fail? double my_sin( double x ) { double pi{ std::numbers::pi }; assert( (x >= 0.0) && (x <= pi/2.0) ); return 4.0*x*x/(pi*pi)*( x - 4.0/pi*x - pi + 3.0 ) + x; }