Sinus i cosinus

0

Jak policzyć sinus i cosinus z rozwinięć w szereg? Ile wyrazów mam zsumować?

user image
user image

public static double sinus(int x) {
		double sin = 1, sin1, sin2;
		for(int i = 1; i < 10; i++) {
			sin1 = x_do_n(x, (2*i +1) ) * x_do_n(-1, i);
			sin2 = k_silnia(2*i + 1);
			sin += sin1/sin2;
		}
		return sin;
	}
	
	public static double cosinus(double x) {
		double cos = 1, cos1, cos2;
		for(int i = 1; i < 10; i++) {
			cos1 = x_do_n(x, 2*i) * x_do_n(-1, i);
			cos2 = k_silnia(2*i);
			cos += cos1/cos2;
		}
		return cos;
	} 

Funkcje silnia i potęgowanie są poprawne.

//W podglądzie wyświetla mi obrazy - wzory..

0

Jeżeli chcesz uzyskać dokładną wartość sinusa, to nieskończoność. Właściwie to do momentu w którym wynik dzielenia licznika przez mianownik dla komputera będzie równy 0.
Na wiki jest ładnie pokazana zależność między ilością iteracji, a dokładnością: http://pl.wikipedia.org/w/index.php?title=Plik:Sintay.svg
Wydaje mi się że jak dojdziesz już do x^13 to jest wystarczająco dokładne.

Nie używaj funkcji do silni. Skorzystaj z tego że n!=(n-2)!*(n-1)*n, albo najlepiej tablicuj wartości silni dla tylu iteracji ile użyjesz.
Pętle niech ci ułatwiają, to nie pascal i możesz inkrementować dowolnie, niekoniecznie o 1. Zacznij se od 3 i dodawaj po 2 i dopóki i<=13.
Potęgowanie -1 też nie wydaje mi się optymalnym pomysłem. Lepszym pomysłem jest coś takiego:

int znak=1;
for(/**/){
  znak*=-1;
}

Ewentualnie 2 wyrazy (tzn + i -) za jednym zamachem załatwić.

0

Sumuj od najmniejszego do największego składnika, aby nie tracić precyzji na ostatnich bitach.

Dla przykładu, jeżeli mamy dwie cyfry znaczące, to:

Przy sumowaniu od najmniejszego:
0.05 + 0.05 + 1 = 0.1 + 1 = 1.1

Przy sumowaniu od największego:
1 + 0.05 + 0.05 = 1 + 0.05 = 1

1

zobacz, ani potęgowania ani silniowania

float Sin(float OOO){
        float O0O=OOO,OO0=OOO;OOO*=OOO;
        int  O00='/'/'/'<<001;
        while(O0O) 
                OO0-=O0O*=OOO/O00++/++O00,
        OO0+=O0O*=OOO/O00++/++O00; 
        return OO0;
} 
0

W Javie oprócz warunku problemem w tej funkcji jest również przecinek, który nie pozwala skompilować kodu. Jeżeli sądząc po formatowaniu w jego miejscu powinien być średnik, to wyniki są takie:
sin(0) = 0,00
sin(30) = 0,51
sin(60) = 0,90
sin(90) = 1,03
sin(120) = 0,72
sin(150) = -0,37
sin(180) = -2,70
sin(210) = -7,08
sin(240) = -14,80
sin(270) = -27,96
sin(300) = -50,01
sin(330) = -86,63
sin(360) = -147,11

Kod testu:

public static void main(String[] args)
{
	double step = 2 * Math.PI / 12; //~30 st.
	for(float alpha = 0; alpha <= Math.PI * 2; alpha += step)
	{
		System.out.printf("sin(%.0f) = %.2f%n",
			alpha * 360 / (Math.PI * 2), Sin(alpha));
	}
}

Jak widać "znośne" wyniki są w pierwszej ćwiartce. W pozostałych nie działa prawidłowo.

0

sens przecinka w C/C++ jest jasny, więc...

0
float Sin(float OOO){
        float O0O=OOO,OO0=OOO;OOO*=OOO;
        int  O00='/'/'/'<<001;
        while(O0O!=000) 
                OO0+=O0O*=-OOO/O00++/++O00;
        return OO0;} 

A tak może być?

0

Jeżeli takie wyniki jak poniżej są akceptowalne:
sin(0) = 0,00
sin(30) = 0,51
sin(60) = 0,91
sin(90) = 1,13
sin(120) = 1,14
sin(150) = 0,93
sin(180) = 0,57
sin(210) = 0,14
sin(240) = -0,27
sin(270) = -0,56
sin(300) = -0,69
sin(330) = -0,63
sin(360) = -0,42
to na pewno może. :)

Dla porównania używając metody Math.sin() dostajemy:
sin(0) = 0,00
sin(30) = 0,50
sin(60) = 0,87
sin(90) = 1,00
sin(120) = 0,87
sin(150) = 0,50
sin(180) = 0,00
sin(210) = -0,50
sin(240) = -0,87
sin(270) = -1,00
sin(300) = -0,87
sin(330) = -0,50
sin(360) = -0,00

0

Do rozwiązania Xitami: lipa... preinkrementacja wartości O0O odbywa się jeszcze przed jakimikolwiek podstawieniami, tak więc np. dla O0O=2 wyrażenie

OO0+=O0O*=-OOO/O00++/++O00;

zostanie zamienione na OO0+=O0O*=-OOO/3/3

 i wtedy wszystko nawala (dla OOO=1 drugi wyraz powinien wynosić -1/6, w tym rozwiązaniu wynosi -1/9).

1 użytkowników online, w tym zalogowanych: 0, gości: 1