I've got a program that calculates the approximation of an arcsin value based on Taylor's series.
My friend and I have come up with an algorithm which has been able to return the almost "right" values, but I don't think we've done it very crisply. Take a look:
double my_asin(double x)
{
double a = 0;
int i = 0;
double sum = 0;
a = x;
for(i = 1; i < 23500; i++)
{
sum += a;
a = next(a, x, i);
}
}
double next(double a, double x, int i)
{
return a*((my_pow(2*i-1, 2)) / ((2*i)*(2*i+1)*my_pow(x, 2)));
}
I checked if my_pow works correctly so there's no need for me to post it here as well. Basically I want the loop to end once the difference between the current and next term is more or equal to my EPSILON (0.00001), which is the precision I'm using when calculating a square root.
This is how I would like it to work:
while(my_abs(prev_term - next_term) >= EPSILON)
But the function double next is dependent on i, so I guess I'd have to increment it in the while statement too. Any ideas how I should go about doing this?
Example output for -1:
$ -1.5675516116e+00
Instead of:
$ -1.5707963268e+00
Thanks so much guys.
using Taylor series for
arcsin
is extremly imprecise as the stuff converge very badly and there will be relatively big differencies to the real stuff for finite number of therms. Also usingpow
with integer exponents is not very precise and efficient.However using
arctan
for this is OKas its Taylor series converges OK on the
<0.0,0.8>
range all the other parts of the range can be computed through it (using trigonometric identities). So here my C++ implementation (from my arithmetics template):Where
T
is any floating point type (float,double
,...). As you can see you needsqrt(x)
,pi=3.141592653589793238462643383279502884197169399375105
,zero=1e-20
and+,-,*,/
operations implemented. Thezero
constant is the target precision.So just replace
T
withfloat/double
and ignore the::
...Issues with your code and question include:
a*((my_pow(2*i-1, 2)) / ((2*i)*(2*i+1)*my_pow(x, 2)))
divides by x2 in each term. This does not matter for the particular value -1 you ask about, but it will produce wrong results for other values, except 1.a
, so you never have both the previous term and the next term at the same time. Instead, create anotherdouble b
so that you have an objectb
for a previous term and an objecta
for the current term, as shown below.Example:
Yes, this might be a way. And what stops you?
Another way would be using the for condition:
Your formula is wrong. Here is the correct formula: http://scipp.ucsc.edu/~haber/ph116A/taylor11.pdf.
P.S. also note that your formula and your series are not correspond to each other.
You can use while like this: