Interesujące pytanie. Podobnie jak Tataryzacja, mam nadzieję, że to nie jest unikanie zadań domowych.
Ten kod wygląda na zapowiedź liczby terminów potrzebnych do uzyskania bezwzględnej precyzji +/- 0,000 000 1 w wyniku dla wszystkich kątów 0 - 90 stopni.
Najwyższy poziom mocy powoduje różnicę x^k/k! do wyniku. Więc
x^k/k! < 1/10^7
Tutaj x jest w radianach więc największą wartość X ~ 1,57 radów. Oznacza to, że tylko seria do mocy 13 daje końcowy okres mniejszy niż 0.000 000 1.
Niestety mój komputer ma zaawansowany wiek (32-bitowy) i każdą próbę obliczenia 13! powoduje przepełnienie. Więc dostosować Horner method trochę, może trochę utraty wydajności, ale unikając silni przepełnienia i umożliwia wstrzymanie jeśli kąt jest niewielka lub jeśli odpowiednia precyzja jest zdobyte przed mocą 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!)
gdzie m jest najwyższa moc potrzebna do żądana absolutna precyzja.
Sin x = x + Sum { iTerm(i) * x^2/(i * (i-1)) }
gdzie
iTerm(0) = x and iTerm(n) = - x^2 * iTerm(n-1)/(i*(i-1)
PS - Dlaczego nie możemy użyć formatowania Math poza Matematyki Stos Exchange? To spowodowałoby, że równania zapisu byłyby o wiele jaśniejsze.
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
Masz nieskończoną pętlę, ponieważ twój stan zachowania nie jest taki, jak chcesz. Prawdopodobnie próbujesz ponownie użyć zmiennych dla 2 różnych celów i nie. Utwórz zmienną delta, w której zapisujesz zmianę dokonaną w tej interakcji i przetestuj wartość detla w warunku. – HopefullyHelpful