Funkcja tablicująca i błąd bezwzględny w Matlabie

0

Link do zadania - http://zapodaj.net/132efb86eff06.jpg.html

Jak do tej pory udało mi się zrobić tyle:

function [y] = sinus(x,dok)
x=0:dok:2*pi;
plot(x,y=sin(x),'--mo');
axis([0 (2*pi) -1 1]);
end

Po podaniu dok=pi/8, x=02*pi, y=sin(x) i wywołaniu funkcji wiem, że x=pi/8 jest równy 0.3927 a jego wartość dla funkcji sin(x) = 0.47943.

Mam w zasadzie trzy pytania:

  • czy na pierwszą część tego zadania taka funkcja wystarczy?
  • jak mam zinterpretować "warunek zatrzymania obliczeń", czyli |Sk| < E?
  • jak WYKREŚLIĆ w Matlabie błąd względny i to jeszcze w zależności od innych składników?

Z góry dzięki za pomoc ;)

0
  1. Nie wystarczy. Masz rozwinąć tę funkcję w Szereg Taylora z zadaną dokładnością dok, czyli szereg jest wzorem na sinus.
  2. Przy rozwijaniu, warunkiem przerwania sumowania jest to, że k - ty wyraz jest bezwzględnie mniejszy od dokładności.
  3. Masz zrobić wykres błędu bezwzględnego w zależności od liczby składników szeregu.
    Wszystko jest wyraźnie objaśnione w temacie.
0
lion137 napisał(a):
  1. Nie wystarczy. Masz rozwinąć tę funkcję w Szereg Taylora z zadaną dokładnością dok, czyli szereg jest wzorem na sinus.
  2. Przy rozwijaniu, warunkiem przerwania sumowania jest to, że k - ty wyraz jest bezwzględnie mniejszy od dokładności.
  3. Masz zrobić wykres błędu bezwzględnego w zależności od liczby składników szeregu.
    Wszystko jest wyraźnie objaśnione w temacie.
  1. Ok, czy w takim razie mam napisać własną funkcję, która na podstawie podanego wzoru na S3 obliczy mi sumę szeregu?
  for i=1:k
    s = ((-1)^i) * x(i)^(2*i+1)/(2i+1);
  end
  1. Później dopytam.
  2. W jaki sposób mam zrobić taki wykres? Stworzyłem zmienną "err" i przypisałem do niej wartość "= abs(dok - sin(pi/8));", zgodnie ze wzorem na błąd bezwzględny. Mam teraz zrobić wykres, na którym będzie zaznaczony ten jeden jedyny punkt?
0
  1. Tak właśnie, Masz napisać swojego sinusa na podstawie rozwinięcia w szereg.
  2. ...
  3. Rozwijasz wielokrotnie w szereg, najpierw Bierzesz jeden wyraz i Liczysz dokładność, potem dwa wyrazy i dokładność i tak dalej... I wykres będzie k (liczba wziętych wyrazów) od błędu bezwzględnego.
0
lion137 napisał(a):
  1. Tak właśnie, Masz napisać swojego sinusa na podstawie rozwinięcia w szereg.
  2. ...
  3. Rozwijasz wielokrotnie w szereg, najpierw Bierzesz jeden wyraz i Liczysz dokładność, potem dwa wyrazy i dokładność i tak dalej... I wykres będzie k (liczba wziętych wyrazów) od błędu bezwzględnego.

Dobra, więc po kolei:

function[y]=sinus(x,dok)
  x=0:dok:2*pi;
  plot(x,y=sin(x),'--mo');
  axis([0 (2*pi)-dok -1 1]);
 
  s = 0;

  for i=1:length(x)
    s = s + (-((x(i)^2)/(2*length(x)*(2*length(x)+1))));
  end
   
end

Ogólnie tak wygląda moja funcja tablicująca. Częśc na górze oblicza wartości sinusa dla podanych x-ów i generuje wykres funkcji.
W petli for zamieściłem wzór za sumowanie szeregu. K-tym składnikiem jest ilość elementów w tablicy x, czyli 17, bo:

Columns 1 through 12:
0.00000 0.39270 0.78540 1.17810 1.57080 1.96350 2.35619 2.74889 3.14159 3.53429 3.92699 4.31969
Columns 13 through 17:
4.71239 5.10509 5.49779 5.89049 6.28319

tyle ich mamy po uwzględnieniu początku (0), końca (2*pi) i skoku (dok) argumentów funkcji.
Suma wyszła = -0.19387.

Z tego trzecieg nic nie rozumiem. W jaki sposób mam policzyć dokładność, skoro to ja ją podaję?
Myśle, aby zrobić w ten sposób, żeby do funkcji:

  for i=1:length(x)
    s = s + (-((x(i)^2)/(2*length(x)*(2*length(x)+1))));
  end

zamiast x-ów podanych na początku jako zakres argumentów funkcji, wstawić po prostu x = pi/8 i wtedy zrobić taki wykres:

plot(-1:length(x)+1, suma kolejnych wyrazów);

Jeżeli pokręciłem to pliss wytłumacz mi to jakoś, bo muszę z tego zrobić sprawozdanie na studia :/

0

Nein, nein, nein; funkcja ma liczyć sinusa z szeregu, wykres Zrobisz potem, z funkcji. Gdzie jest warunek przerwania w pętli, zależny od dokładności? Nie Masz obliczyć dokładności, tylko wykres błędu w zależności od liczby wyrazów w rozwinięciu. Poważnie, wydaje mi się, że za mało z tego Rozumiesz, żeby to zakodować.

0
lion137 napisał(a):

Nein, nein, nein; funkcja ma liczyć sinusa z szeregu, wykres Zrobisz potem, z funkcji. Gdzie jest warunek przerwania w pętli, zależny od dokładności? Nie Masz obliczyć dokładności, tylko wykres błędu w zależności od liczby wyrazów w rozwinięciu. Poważnie, wydaje mi się, że za mało z tego Rozumiesz, żeby to zakodować.

Dobra:

function[y]=sinus(x,dok)
  x=0:dok:2*pi;
  plot(x,y=sin(x),'--mo');
  axis([0 (2*pi)-dok -1 1]);
  
  s = 0;
  k = length(x);
  
  for i=1:k
    if k == 1
      s = x(1);
    elseif k>1 && mod(k,2) == 0
      s = -((x(i).^(2*k+1)) / (factorial(2*k+1)));
    elseif k>1 && mod(k,2) > 0
      s = ((x(i).^(2*k+1)) / (factorial(2*k+1)));
    elseif s<dok
      break;
  end
   
end

Coś takiego wyskrobałem. Oczywiście nie działa... w ogóle nie ogrania, że tam jest pętla.
Rzuć na to okiem. Jeżeli będzie całkowicie źle, to się poddaję.

0

Pewnie, że nie działa, ale nie ma co się załamywać, tylko poduczyć:). Wywal to rysowanie z funkcji sinus, sinus ma być oddzielny, dopiero na jego podstawie Stworzysz wektor y stablicowanych wartości, a na podstawie wektora i x - sów Narysujesz wykres. nie mam matlaba ale tak to wygląda w pseudokodzie (Python):

def my_sin(x, e):
	s1 = x
	if abs(s1) < e: return s1
	i = 0
	s = x
	while i < 1000:
		sk = s1 * ((-1) * (x * x) / (2*(i + 1) * (2 * (i + 1) + 1)))
		s += sk
		if abs(sk) < e: return s
		s1 = sk
		i += 1
	return float('nan')


print(my_sin(2.0, 1.0))  # -> 0.933333333333
print(my_sin(2.0, 0.03)) # -> 0.907936507937
print(sin(2.0)) 		 # -> 0.909297426826

Pierwszym elementem jest s1 czyli x. Iteruję do tysiąca, i jak nie wejdzie w zadaną dokładność to zwracam nan (not a number), żeby dawało użytkownikowi informację, że nie da się uzyskać zadanej dokładności (np. jak ktoś wpisze e = 0). Ta linijka:
sk = s1 * ((-1) * (x * x) / (2*(i + 1) * (2 * (i + 1) + 1)))
to bezpośrednie zapisanie ich warunku na k - ty element (tak jest łatwiej nie trzeba ustalać znaku , ani liczyć silni).
Potem sumowanie (trzeba pamiętać, że pierwszym elementem sumy jest x, a nie zero), sprawdzenie warunku i i ewentualny zwrot wyliczonego sinusa i iteracja:
s1 = sk
czyli s - k minus pierwszy element staje się s katym; dalej inkrementacja licznika i.
Widać jak się zmienia dokładność wraz z pomniejszaniem epsilona (e), sin(2.0) liczy sinusa z standardowej biblioteki.

0
lion137 napisał(a):

Pewnie, że nie działa, ale nie ma co się załamywać, tylko poduczyć:). Wywal to rysowanie z funkcji sinus, sinus ma być oddzielny, dopiero na jego podstawie Stworzysz wektor y stablicowanych wartości, a na podstawie wektora i x - sów Narysujesz wykres. nie mam matlaba ale tak to wygląda w pseudokodzie (Python):

def my_sin(x, e):
	s1 = x
	if abs(s1) < e: return s1
	i = 0
	s = x
	while i < 1000:
		sk = s1 * ((-1) * (x * x) / (2*(i + 1) * (2 * (i + 1) + 1)))
		s += sk
		if abs(sk) < e: return s
		s1 = sk
		i += 1
	return float('nan')


print(my_sin(2.0, 1.0))  # -> 0.933333333333
print(my_sin(2.0, 0.03)) # -> 0.907936507937
print(sin(2.0)) 		 # -> 0.909297426826

Pierwszym elementem jest s1 czyli x. Iteruję do tysiąca, i jak nie wejdzie w zadaną dokładność to zwracam nan (not a number), żeby dawało użytkownikowi informację, że nie da się uzyskać zadanej dokładności (np. jak ktoś wpisze e = 0). Ta linijka:
sk = s1 * ((-1) * (x * x) / (2*(i + 1) * (2 * (i + 1) + 1)))
to bezpośrednie zapisanie ich warunku na k - ty element (tak jest łatwiej nie trzeba ustalać znaku , ani liczyć silni).
Potem sumowanie (trzeba pamiętać, że pierwszym elementem sumy jest x, a nie zero), sprawdzenie warunku i i ewentualny zwrot wyliczonego sinusa i iteracja:
s1 = sk
czyli s - k minus pierwszy element staje się s katym; dalej inkrementacja licznika i.
Widać jak się zmienia dokładność wraz z pomniejszaniem epsilona (e), sin(2.0) liczy sinusa z standardowej biblioteki.

Dzięki ;) Wiem, że data science nie jest dla mnie.
Mam ostatnią prośbę, dałbyś radę zinterpretować ten kod na Matlaba, ew. Octave -> z tego programu korzystam, bo Matlab jest płatny, chociaż używamy go na studiach.

function[y]=sinus(x,dok)
  s1 = x;
  if (abs(s1)) < dok
      y(1) = s1;
  end
  i = 0;
  s = x;
  while i < 1000
    sk = s1 * ((-1) * (x * x) / (2*(i + 1) * (2 * (i + 1) + 1)));
    s = s + sk;
    if (abs(sk)) < e
      y(1) = s;
    end  
    s1 = sk;
    i = i + 1;
  end
end

Tak to zaimplementowałem po swojemu. Kiedy wpisuję sinus(2.0,1.0), to zawsze pokazuje 0.90930, tak jak przy użyciu standardowej funkcji sin(2.0).

0

W warunku, w pętli masz e, a nie dok.

0
lion137 napisał(a):

W warunku, w pętli masz e, a nie dok.

Fakt, moje niedopatrzenie, ale wiąż mam:

screenshot-20190624172636.png

0

Nie przerywasz pętli gdy zachodzi warunek i do końca Ci nadpisuje y(1), stąd to. Przerwij pętlę od razu, jak się znajdzie w "ifie".

0
lion137 napisał(a):

Nie przerywasz pętli gdy zachodzi warunek i do końca Ci nadpisuje y(1), stąd to. Przerwij pętlę od razu, jak się znajdzie w "ifie".

function[y]=sinus(x,dok)
  s1 = x;
  if (abs(s1)) < dok
      break;
  end
  i = 0;
  s = x;
  while i < 1000
    sk = s1 * ((-1) * (x * x) / (2*(i + 1) * (2 * (i + 1) + 1)));
    s = s + sk;
    if (abs(sk)) < dok
      break;
    end  
    s1 = sk;
    i = i + 1;
  end
end

Nic nie pomaga :/

screenshot-20190624175616.png

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