1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// Evaluates power series for sin(x) and cos(x) to n terms in 2 ways
// values entered are not checked so enter carefully x = -PI to +PI
// and n not too high. Keep eye on value of n! vs. DBL_MAX in output
// NOTE: n=12 gives about 10 digit accuracy (series converges rapidly)
// so no need for high n values
#include <iostream>// for use of cin, cout
#include <iomanip>// for use of setprecision
#include <cstdio>// for use of gets(), scanf()
#include <cmath>// for use of sin, cos, pow functions
#include <float.h>// for use of the constant DBL_MAX
using namespace std;
double factorial(double n)// not needed by SineN2, CosineN2 functions
{
if (n<=1.0)
return(1.0);
else
n=n*factorial(n-1.0); // notice we just keep calling this over until we get to 1!
return(n);
}
double SineN(const double& x, const int& n )// replaces first
{
double sum = 0.0;
if(n > 0)
for(int j=0; j<n; j++)
{ // successive terms are to alternate sign
if(j%2)// j is odd
sum -= pow(x,(double)(2*j+1))/factorial((double)(2*j+1));
else// j is even
sum += pow(x,(double)(2*j+1))/factorial((double)(2*j+1));
}
return sum;
}// end of SineN()
// this method uses the recursion relation for the series
// to generate the next coefficient from the last.
// Advantages: 1) No need to find n! for each term.
// 2) No need to call pow(x,n) each term.
double SineN2(const double& x, const int& n, double* p_err )
{
double a = 1.0*x;// 1st term
double sum = 0.0;
if(n > 0)
{
for(int j=1; j<=n; j++)// for sine
{
sum += a;
a *= -1.0*x*x/( (2*j+1)*(2*j) );// next term from last
// sum += a;
}
*p_err = a;// max. error = 1st term not taken for alternating series
}
else
cout << " n must be > 0";
return sum;
}// end of SineN2()
double CosineN(const double& x, const int& n )// replaces second
{
double sum = 1.0;
if(n > 0)
for(int j=1; j<n; j++)
{
if(j%2)// j is odd
sum -= pow(x,(double)(2*j))/factorial((double)(2*j));
else// j is even
sum += pow(x,(double)(2*j))/factorial((double)(2*j));
}
return sum;
}// end of CosineN()
double CosineN2(const double& x, const int& n, double* p_err )
{
double a = 1.0;// 1st term
double sum = 0.0;
if(n > 0)
{
for(int j=0; j<n; j++)// for cosine
{
sum += a;
a *= -1.0*x*x/( (2*j+1)*(2*j+2) );// next term from last
// sum += a;
}
*p_err = a;// max. error = 1st term not taken for alternating series
}
else
cout << " n must be > 0";
return sum;
}// end of CosineN2()
int main()
{
int n = 0;// number of terms in series
double x = 0.0;// series parameter. Give value in radians
double errorAmount = 0.0;// new functions find this value
char repeat = 'y';
do// until user is done
{
cout << "Enter x (in radians): " ;
cin >> x;
cout << "Enter n: " ;// the # of terms in the series. Try entering 5 - 15 or so
cin >> n;
cout << "n! = " << factorial((double)n) << endl;
cout << "DBL_MAX = " << DBL_MAX << endl << endl;
cout << setprecision (10);// display result to 10 decimal places
cout << "SineN = " << SineN(x,n) << endl;// using a power series
cout << "SineN2 = " << SineN2(x,n,&errorAmount) << endl;// using recursion relation
cout << "sin(x) = " << sin(x) << endl;// check against math library function
cout << "errorAmount = " << errorAmount << endl << endl;// display max. error
cout << "CosineN = " << CosineN(x,n) << endl;
cout << "CosineN2 = " << CosineN2(x,n,&errorAmount) << endl;
cout << "cos(x) = " << cos(x) << endl;
cout << "errorAmount = " << errorAmount << endl << endl;
cout << "repeat (y/n)? " << flush;
cin >> repeat;
}while( repeat=='y');
return 0;
}
|