• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

szereg taylora dla exp(x) w c++

0 głosów
2,460 wizyt
pytanie zadane 12 marca 2016 w C i C++ przez muscler Użytkownik (720 p.)

Witam! 

Tak więc, poniżej podam najpierw treść zadania z którym mam problem.

"Zaimplementuj w języku „C/C++” algorytm obliczający przybliżone wartości funkcji f(x) = exp(x) dla x €[-30, 30], poprzez sumowanie N wyrazów rozwinięcia tej funkcji w szereg Taylora wokół x = 0. Zbadaj jak zmieniają się błędy względne przybliżenia funkcji w tym algorytmie, przy wzrastającej liczbie N € [1, 1000]. Wyjaśnij przyczyny obserwowanych błędów i ich zmian ze wzrostem N. Następnie dokonaj takiej modyfikacji algorytmu, i wybierz takie N, aby uzyskać dokładność maszynową dla dowolnego x € [-30, 30]. W obliczeniach zastosuj zmienne podwójnej precyzji."

Natknąłem się na problem już na początku pisania programu, a jest nim złe obliczanie wartości exp(x) szeregiem taylora. Dla x>=-3 wypisuje przyblizone wartosci do tych prawdziwych lecz dla x<-3 wypisuje zupełnie inne wartosci.. ktoś wie czym to moze byc spowodowane? Drugie pytanie odnosnie wartości N. W zadaniu jest napisane, że ma ona wartosc od 1 do 1000. U mnie w przykładzie do wartosci n=13 wypisuje dobre wyniki, lecz im większe N to te wyniki są coraz bardziej różne od poprawnych. Ma ktoś chwilę na to spojrzeć? :) Poniżej wklejam moja część kodu.

#include "stdafx.h"
#include <iostream>

using namespace std;

 double szereg(int x)
{
	double y = 1;
	int n = 1, m = 1;
	for (int i = 1; i <= 13; i++)
	{
		m *= i;
			y += (pow((double)x, (double)i)) / m;
	}
	return y;
}


int _tmain(int argc, _TCHAR* argv[])
{
	cout << "x\t\texp(x)\t\tszereg Taylora\n" << endl;
	double o;
	int n = 1, m = 1;
	for (int i = -30; i <= 30; i++)
	{
		double z = exp(i);
		o = szereg(i);
		cout << i << "\t\t" <<z <<"\t\t"<<o  << endl;
	}


	system("PAUSE");
	return 0;
}

 

1 odpowiedź

+4 głosów
odpowiedź 12 marca 2016 przez Benek Szeryf (89,080 p.)
wybrane 12 marca 2016 przez muscler
 
Najlepsza

Dla x>=-3 wypisuje przyblizone wartosci do tych prawdziwych lecz dla x<-3 wypisuje zupełnie inne wartosci.. ktoś wie czym to moze byc spowodowane?

Wartością reszty Peano. Zauważ, że rozwijasz funkcję wokół punktu x=0, co oznacza iż tylko w niewielkim otoczeniu tego punktu szereg dostatecznie dobrze aproksymuje się do prawdziwej funkcji. Nawet masz wskazówkę w zadaniu, że to o to może chodzić, gdyż masz dokonać modyfikacji programu, tak by dla dowolnego argumentu szereg dość dobrze przybliżał eksponentę.

Drugie pytanie odnosnie wartości N. W zadaniu jest napisane, że ma ona wartosc od 1 do 1000. U mnie w przykładzie do wartosci n=13 wypisuje dobre wyniki, lecz im większe N to te wyniki są coraz bardziej różne od poprawnych.

Należy rozumieć to tak, że zwiększając liczbę N, dodajesz do szeregu kolejne wyrazy. Im bliżej jesteś punktu, wokół którego rozwinąłeś szereg, tym więcej wyrazów szeregu (większe N) da dokładniejszy wynik. Z drugiej strony, błędy coraz bliższych punktów z sąsiedztwa będą narastać, ponieważ wzór na szereg Taylora jest idealizacją, dla N dążącego do nieskończoności.

Innymi słowy masz grę dwóch parametrów: im mniejsze sąsiedztwo rozważysz, tym mniejsze błędy przy większym N, ale z drugiej strony musisz zagęścić podział przedziału [-30,30], czyli np. nie skakać co 1, ale co 0.05. I teraz Twoim zadaniem jest znaleźć odpowiednie N oraz zagęszczenie przedziału, by uzyskać maszynową dokładność. Zdaje się, że jesteś studentem, bo w szkole średniej byłoby to zbyt ambitne zadanie. Powodzenia!

komentarz 12 marca 2016 przez muscler Użytkownik (720 p.)

Tak tak, student :) 

Czyli teraz do tego wyniku co mi wychodzi muszę jeszcze dodawać wartość błędu tak? 

Dodałem wartość błędu bezwzględnego i wartosci przy n=200 dla ujemnych x są juz duzo bardziej dokładne lecz jeszcze nie wszystkie :( Dobrze myślę? Tylko teraz jeszcze dla n>200 dostaję zamiast niektórych liczb : -1.#IND .Wyczytałem coś takiego :  If you get 1.#IND or nan, look for illegal operations.  Lecz zupełnie nie wiem gdzie może mi się generować ten błąd. Stale szukam odpowiedzi, ale może ktoś miał podobny problem i wie jak to ogarnąć? :)

komentarz 12 marca 2016 przez Benek Szeryf (89,080 p.)

W ten sposób wychodzisz poza zakres liczb, nawet typu long double, stąd te komunikaty. Obliczasz kolejne czynniki (x^n)/n!, i choć dla dowolnego x taki ciąg zbiega się do zera przy n dążącym do nieskończoności, to jednak jego wyrazy są olbrzymie, zwłaszcza dla x=30 i n=50. Można jednak temu zaradzić.

Najprościej jest, na przykład licząc wartość dla x=7, rozwinąć szereg wokół właśnie tego punktu. Dzięki temu zyskalibyśmy wiarygodne wyniki nawet dla małych wartości N. To jednak numerycznie się nie uda, bo w rozwinięciu szeregu wokół punktu innego niż 0 pozostanie nadal funkcja exp(x) - ma ona tę własność, że po zróżniczkowaniu pozostaje tą samą funkcją. Wiemy, że to nie zadziała. Pozostaje nam tylko rozwinięcie w szereg dla x=0, bo wtedy jej pochodne staną się po prostu 1 = exp(0). W tym momencie należy skorzystać z właściwości potęgowania. Gdy chcemy policzyć exp(7.32), to możemy to zapisać jako

exp(7.32) = exp(1)*exp(1)*exp(1)*exp(1)*exp(1)*exp(1)*exp(1)*exp(0.32)

A to już możemy policzyć, bo jak sam zauważyłeś, wartości wokół 0 dość dobrze odtwarzają funkcję exp(x). Zwróć uwagę, aby nie przekazywać funkcji szereg() wartości int, tylko double, bo 0.32 zaokrągli Ci do 0.

komentarz 12 marca 2016 przez muscler Użytkownik (720 p.)
Działa! dzięki wielkie! :)
komentarz 24 kwietnia 2016 przez carlos Nowicjusz (100 p.)
Czy mógłbyś podać kod po zmianie bo mimo zastosowania porad do mojego kodu jakie tu Benek napisał nadal nie mieszcze się z liczbami.

Podobne pytania

0 głosów
0 odpowiedzi 296 wizyt
pytanie zadane 18 grudnia 2020 w C i C++ przez Empire Nowicjusz (140 p.)
0 głosów
2 odpowiedzi 2,976 wizyt
pytanie zadane 30 października 2015 w C i C++ przez Moonshine Mądrala (6,360 p.)
0 głosów
0 odpowiedzi 311 wizyt
pytanie zadane 2 marca 2019 w C# przez Piotr Brodziak Początkujący (390 p.)

89,693 zapytań

138,297 odpowiedzi

309,243 komentarzy

59,623 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...