Computing sin (x) w / oMath and using loops only in java

I need to calculate Math.sin (x) using the Taylor series:

P

Σ (-1) ^ i * (x ^ (2i + 1) / (2i + 1)!) As n → ∞

= 0

Therefore, I am allowed to use loops (without recursion), and I cannot use the Math class. Here is how far I came:

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 interruption condition is not entirely correct (-1 * 10 ^ -7 or 1 * 10 ^ -7), the returned result is NaN. I was already looking for him, but now I'm a little overdoing it, so I hope someone can help me. :)

Thanks in advance!

+6
source share
3 answers
  • You did not initialize i.
  • You checked the final conditional result, not the taylor element of the amount.
  • You left potenz2 and fac elements to keep the spiral out of control, and not reset for each new element in the series.
  • In the end they will reach infinity and infinity, separate them and get NaN. NaN added to the result of NaN execution, and which actually returns true for the conditional and exits the loop (NaN has odd effects with conditional expressions).

Here's a working code with comments for 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 someone needs this somehow for some kind of production work at a speed that is critical (and a less erroneous answer, although Math is actually used in this case), and not "can anyone do my homework for me is optimized code here:

 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; } 
+5
source

You do not change the value of the result variable :)

Also, the variable I have not been declared. Indeed, it would be much easier if you posted a sample working code.

Once this is fixed, you should compare the change between the previous calculation and the last value of your delta (0.000001), and not the result itself. Your cycle should end as soon as the series converges to the desired accuracy, and not when the calculated value is really small.

You also have a couple of errors, such as a one-after-one error in the loop counters, rather than reinitializing the accumulated variables between loop iterations. It is easily parsed by passing arguments 0 and Pi.

+1
source

Interest Ask. Like Tatarize, I hope this is not an evasion of homework.

This code predicts the number of terms needed to obtain absolute accuracy +/- 0.000 000 1 as a result for all angles 0 - 90 degrees.

The highest power term distinguishes x ^ k / k! to the result. So,

  x^k / k! < 1 / 10^7 

Here x is in radians, so the largest value of x is ~ 1.57 rad. This means that only a series up to capacity 13 will give you a final term of less than 0.000 000 1.

Unfortunately, my computer has an advanced age (32-bit) and any attempt to calculate 13! causes overflow. Therefore, I am adapting the Horner method a bit, possibly losing some efficiency, but avoiding factorial overflow and allowing to stop if the angle is small or if adequate accuracy is reached up to a power of 13.

  Sin x = x - x^2(x/3! - x^2(x/5! - x^2(x/7! - . . . - x^2(x/(m-1)!- x^2(x/m!) 

where m is the highest power required for the required absolute accuracy.

  Sin x = x + Sum { iTerm(i) * x^2 / (i * (i-1)) } 

Where

  iTerm(0) = x and iTerm(n) = - x^2 * iTerm(n-1)/(i*(i-1) 

PS - Why can't we use Math formatting outside of the Exchange Mathematics Stack Exchange? This would greatly simplify the written equations.

 public class TrigByPoly { // No constructor used. public static void main(String[] args) { double x0 = 0, x1 = Math.PI/12, x2 = Math.PI/6, x3 = Math.PI/4, x4 = Math.PI/3, x5 = Math.PI/2; double sinx0 = SinByPoly(x0), sinx1 = SinByPoly(x1), sinx2 = SinByPoly(x2), sinx3 = SinByPoly(x3), sinx4 = SinByPoly(x4), sinx5 = SinByPoly(x5); System.out.println("Sin(0) to 7 decimal places is : " + sinx0); System.out.println("Sin(15) to 7 decimal places is : " + sinx1); System.out.println("Sin(30) to 7 decimal places is : " + sinx2); System.out.println("Sin(45) to 7 decimal places is : " + sinx3); System.out.println("Sin(60) to 7 decimal places is : " + sinx4); System.out.println("Sin(90) to 7 decimal places is : " + sinx5); } public static double SinByPoly(double x) { int i = 0; // Polynomial order indicator. double x2 = x * x, iTerm, sinx = 0; if (x < 0.0084) // Limiting angle for Sinx = x to 10^-7 precision. sinx = x; else { sinx = x; iTerm = sinx; i = 3; do { iTerm = - x2 * iTerm / ( i * (i - 1)); sinx += iTerm; i = i + 2; } while (i < 14 && (iTerm > 0.0000001 || -iTerm > 0.0000001)); } return sinx; } } OUTPUT ====== Sin(0) to an absolute precision of 1.0E-7 is : 0.0 Sin(15) to an absolute precision of 1.0E-7 is : 0.2588190618109834 Sin(30) to an absolute precision of 1.0E-7 is : 0.4999999918690232 Sin(45) to an absolute precision of 1.0E-7 is : 0.7071067829368671 Sin(60) to an absolute precision of 1.0E-7 is : 0.8660254450997811 Sin(75) to an absolute precision of 1.0E-7 is : 0.9659258210120795 Sin(90) to an absolute precision of 1.0E-7 is : 0.999999943741051 
+1
source

Source: https://habr.com/ru/post/1012492/


All Articles