I've got to calculate Math.sin(x) using the Taylor Series:
n
∑ (-1)^i* (x^(2i+1) / (2i+1)!) for n → ∞
i=0
Therefore, I am only allowed to use loops (no recursion) and I may not use the Math class. This is how far I've come:
public double sinLoops(double x) {
int potenz1;
double potenz2 = x;
double fac = 1;
double result = 0;
do {
if ((i % 2) == 0) {
potenz1 = 1;
} else {
potenz1 = (-1);
}
for (int counter = 1; counter < (2 * i + 1); counter++) {
potenz2 *= x;
}
for (int counter2 = (2 * i + 1); counter2 >= 1; counter2--) {
fac *= counter2;
}
result += potenz1 * potenz2 / fac;
i++;
} while (result > 0.0000001 || result < -0.0000001);
return result;
}
However, I think my break condition isn't quite correct (-1*10^-7 or 1*10^-7),the returned result is NaN. I've already looked it up, but I am kinda overchallenged right now, so I'm hoping someone can help me with this. :)
Thanks in advance!
Here's the working code with comments at the problems.
public double sinLoops(double x) {
int i = 0; //this didn't exist.
double result = 0;
double seriesElement; //You need the individual taylor series element.
do {
double potenz2 = x; //these need to be reset each time.
double fac = 1; //if not they overflow and infinity/infinity is NaN and it exits.
int potenz1 = ((i & 1) == 1) ? -1 : 1; //this is just short hand.
for (int counter = 1; counter < (2 * i + 1); counter++) {
potenz2 *= x;
}
for (int counter2 = (2 * i + 1); counter2 >= 1; counter2--) {
fac *= counter2; //we could actually keep the last iteration and do 2*(i-1)+1 to 2*i+1 each new i.
}
seriesElement = potenz1 * potenz2 / fac; //we need to save the value here.
result += seriesElement; //we are summing them in the results.
i++;
} while (seriesElement > 0.0000001 || seriesElement < -0.0000001); //We check this conditional against the series element, *NOT THE RESULT*
return result;
}
In case anybody needs this somehow for some kind of production work with speed being critical (and a less wrong answer, though really in that case use Math), rather than the "can somebody do my homework for me" type here's the optimized code:
public double sinLoops(double x) {
double result = 0, powerx = -1, fac = 1;
int i = 0, n, m = 0;
while (true) {
n = m;
m = (i++*2) + 1;
powerx *= -1;
while (n < m) {
powerx *= x;
fac *= ++n;
}
if ((Double.isInfinite(fac)) || (Double.isInfinite(powerx))) break;
result += powerx / fac;
}
return result;
}
You are not modifying the value of result variable :)
Also variable i is undeclared. Really, would be much easier if you posted a working code sample.
Once that is fixed, you should be comparing the change between previous calculation and the latest to your delta value (0.000001), not result itself. Your loop needs to end once series converges to the desired precision, not when the calculated value is really small.
You also have a couple of mistakes like off-by-one error in loop counters and not re-initializing accumulating variables between loop iterations. It is easily analyzed by running through the case of arguments of 0 and Pi.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With