How do I end this while loop with a precision of 0.00001 ([C++],[Taylor Series])? -
i'm working on program approximates taylor series function. have approximate taylor series function stops approximating sin function precision of .00001. in other words,the absolute value of last approximation minus current approximation equals less or equal 0.00001. approximates each angle 0 360 degrees in 15 degree increments. logic seems correct, cannot figure out why getting garbage values. appreciated!
#include <math.h> #include <iomanip> #include <iostream> #include <string> #include <stdlib.h> #include <cmath> double fact(int x){ int f = 1; for(int = 1; <= x; i++){ f*=i; } return f; } double degreestoradians(double angle_in_degrees){ double rad = (angle_in_degrees*m_pi)/180; return rad; } using namespace std; double mysine(double x){ int current =99999; double comsin=x; double prev=0; int counter1 = 3; int counter2 = 1; while(current>0.00001){ prev = comsin; if((counter2 % 2) == 0){ comsin += (pow(x,(counter1))/(fact(counter1))); }else{ comsin -= (pow(x,(counter1))/(fact(counter1))); } current=abs(prev-comsin); cout<<current<<endl; counter1+=2; counter2+=1; } return comsin; } using namespace std; int main(){ cout<<"angle\tsine"<<endl; (int = 0; i<=360; i+=15){ cout<<i<<"\t"<<mysine(degreestoradians(i)); } }
here example illustrates how go doing this. using pow function , calculating factorial @ each iteration inefficient -- these can maintained running values updated alongside sum during each iteration.
in case, each iteration's addend product of 2 factors: power of x , (reciprocal) factorial. 1 iteration's power factor next iteration's, multiply x*x. 1 iteration's factorial factor next iteration's, multiply ((2*n+1) + 1) * ((2*n+1) + 2), before incrementing n (the iteration number).
and because these 2 factors updated multiplicatively, not need exist separate running values, can exists single running product. helps avoid precision problems -- both power factor , factorial can become large quickly, ratio of values goes 0 relatively gradually , well-behaved running value.
so example maintains these running values, updated @ each iteration:
- "sum" (of course)
- "prod", ratio: pow(x, 2n+1) / factorial 2n+1
- "tnp1", value of 2*n+1 (used in factorial update)
the running update value, "prod" negated every iteration in order to factor in (-1)^n.
i included function "xlatedsine". when x far away zero, sum requires more iterations accurate result, takes longer run , can require more precision our floating-point values can provide. when magnitude of x goes beyond pi, "xlatedsine" finds x, close zero, equivalent value sin(x), uses shifted x in call maclaurinsine.
#include <iostream> #include <iomanip> // importing cmath seemed wrong lol, define abs , pi static double abs(double x) { return x < 0 ? -x : x; } const double pi = 3.14159265358979323846; // taylor series x==0 sin(x): // // sum(n=[0...oo]) { ((-1)^n) * (x^(2*n+1)) / (2*n + 1)! } // double maclaurinsine(double x) { const double xsq = x*x; // cached constant x squared int tnp1 = 3; // 2*n+1 | n==1 double prod = xsq*x / 6; // pow(x, 2*n+1) / (2*n+1)! | n==1 double sum = x; // sum after n==0 for(;;) { prod = -prod; sum += prod; static const double minupdate = 0.00001; // try 0 -- factorial dominate power of x, if(abs(prod) <= minupdate) { return sum; } // update 2 factors in prod prod *= xsq; // add 2 power factor's exponent prod /= (tnp1 + 1) * (tnp1 + 2); // update factorial factor 2 iterations tnp1 += 2; } } // xlatedsine translates x angle close 0 produce equivalent result. double xlatedsine(double x) { if(abs(x) >= pi) { // use int casting fmod pi (but symmetric zero). // keep in mind big x overflow int, // such large double value have lost precision // @ sub-pi-sized scale doing in legit fashion // disappoint. const int p = static_cast<int>(x / pi); x -= pi * p; if(p % 2) { x = -x; } } return maclaurinsine(x); } double degreestoradians(double angle_deg) { return pi / 180 * angle_deg; } int main() { std::cout<<"angle\tsine\n" << std::setprecision(12); for(int = 0; i<=360; i+=15) { std::cout << << "\t" << maclaurinsine(degreestoradians(i)) << "\n"; //std::cout << << "\t" << xlatedsine(degreestoradians(i)) << "\n"; } }
Comments
Post a Comment