funkcja tablicowanie w szereg Taylora

Odpowiedz Nowy wątek
2019-01-11 16:32
0

Mam problem z napisaniem funkcji która przez iterację bedzię liczyła następny wyraz szeregu. Szereg:sqrt(1+x)= 1 + 1/2 x - 1/8 x^2 + 1/16 x^3 - 5/128 x^4 + 7/256 x^5 - 21/1024 x^6 + 33/2048 x^7 - 429/32768 x^8 + 715/65536 x^9 - 2431/262144 x^10 + 4199/524288 x^11 - 29393/4194304 x^12 + 52003/8388608 x^13

#define li 100 //liczba iteracji do szeregu
//tablicowanie fcji sin w <a,b> - szereg + funkcja biblioteczna
//definicja funkcji szereg; x - parametr formalny
double szereg(double x)
{
double s, w;
int i;
s=x;
w=1+x;
for(i=1;i<=li;i+=2)
{
    // sqrt(1+x)=1 + 1/2 x - 1/8 x^2 + 1/16 x^3 - 5/128 x^4 + 7/256 x^5 - 21/1024 x^6
 w=-w*x/2*i //?
 s=s+w;
}
return s;
}
Rozumiem, że Chcesz policzyć n - tą sumę, czyli zsumować n pierwszych wyrazów szeregu? Czy może sqrt(1+x)z jakąś dokładnością? - lion137 2019-01-11 17:07
tak, używając poprzedniego wyrazu - labajek 2019-01-14 16:08
Czyli rekurencyjnie, na jedno wychodzi. - lion137 2019-01-14 16:13

Pozostało 580 znaków

2019-01-11 17:06
1

https://dsp.krzaq.cc/post/445/jak-zadawac-pytania-na-forum/
Tytuł dobry
Treść, kiepska, bo nie wiadomo z czym masz problem i jakie masz wymagania co do rozwiązania.
Jest parę hasłeł, które sugerują coś bardziej ogólnego niż szereg Taylora dla f(x) = \sqrt{x + 1}

BTW: 1/2 w C daje 0!


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2019-01-11 17:07

Pozostało 580 znaków

2019-01-11 18:55
1

taylorSeries sumuje n pierwszych wyrazów szeregu, przy okazji taylor liczy n-ty wyraz, coś to podejrzanie wolno zbieżne, ale wynik wygląda dobrze (dla x = 1 powinno dać pierwiatek z dwóch)

// Taylor sqrt(1 + x), https://planetmath.org/taylorexpansionofsqrt1x
#include <iostream>
#include <cmath>

unsigned long fact(unsigned long n) {
    if (n == 0) return 1L;
    unsigned long p = 1L;
    while (n > 0){
        p *= n;
        n--;
    }
    return p;
}

int sign(int n) {
    return powl(-1, n - 1);
}

double f(unsigned long n) { // ułamek w Szeregu Taylora
    return  fact(2 * n - 3) / ( powl(2, 2 * n - 2) * fact(n) * fact(n - 2) );
}

double taylor(unsigned long i, double x) {
    return sign(i) * f(i) * pow(x, i);
}

double taylorSeries(double x, int maxIter) { 
    if (maxIter == 0) return 1;
    if (maxIter == 1) return 0.5 * x + 1;
    int i{2};
    double s{0.5D * x + 1};
    while (i < maxIter) {
        s = s + taylor(i, x);
        i++;
    }
    return s;

}

int main () {
    std::cout << taylorSeries(1, 20) << "\n"; // -> 1.41599
    return 0;
}

edytowany 1x, ostatnio: lion137, 2019-01-12 00:39
prog.cpp:30:14: error: suffix for double constant is a GCC extension [-Werror] double s{0.5D * x + 1}; - enedil 2019-01-12 03:39
Zapominam, że nie wszyscy używają gcc, to musi sobie zmienić zgodnie ze swoim kompilatorem. - lion137 2019-01-12 13:19
No właśnie nie musi, ten dodatek jest zbędny, i tak wynik jest doublem. - enedil 2019-01-12 13:27
To spoko, tak myślałem, ale dałem na wszelki wypadek. - lion137 2019-01-12 13:29

Pozostało 580 znaków

2019-01-12 00:09
1

@lion137 ten twój kod ma dużo numerycznych kwiatków.
Matematycznie może wygląda poprawnie, ale od strony informatycznej tragedia.
Samo sign to absurd. Do tego silnia jest źle liczona (szybko rośnie i nie zmieści ci się w unsigned long).
W takich zadaniach kolejne elementy szeregu liczy się na podstawie elementu poprzedniego.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22, 2019-01-12 00:10
Właśnie, cały turniej (brydż) mnie coś gryzło:-), że z tą silnią jest nie tak, trzeba to skrócić. A czemu sign to takie ``Zuo```? - lion137 2019-01-12 00:19
używasz ciężkiej funkcji do czegoś prostego. - MarekR22 2019-01-12 00:20
DLa przejrzystości, złożonościowo, to i tak nie zaszkodzi. - lion137 2019-01-12 00:20
W tym modelu (jaki przyjąłem) nie da się uprościć tej silni, jest to zbieżne, ale dokładność jest słaba, bo ten ułamek szybko ucieka do zera. Nie wiem jak tego uniknąć, licząc, jak Piszesz, z poprzednich elementów. - lion137 2019-01-12 00:38

Pozostało 580 znaków

2019-01-12 04:17
1

@lion7 zauważ taką relację rekurencyjną (o ile się nie pomyliłem):

taylor(i + 1, x) = (-1) \cdot \frac {(2i - 1) \cdot (2i - 2)} {4 (i+1)*(i+2)*i*(i-1)} \cdot (1+x)^{-1} \cdot taylor(i, x)

A w kwesti zła funkcji sign, oto lepsza implementacja:

int sign(int n)
{
if (n % 2 == 0) return -1;
return 1;
}

Edycja: istotnie, jednak się pomyliłem. Oto poprawny wzór:

taylor(i+1, x) = -\frac 1 4 \cdot \frac{(2i-1)(2i-2)}{(i+1)(i-1)} \cdot taylor(i, x) / (1+x)
edytowany 6x, ostatnio: enedil, 2019-01-12 14:26
Co to jest n w tej rekurencji? Jaki jest jej warunek stopu? - lion137 2019-01-12 13:30
Czego w ogóle dotyczy pytanie? To jest tylko relacja rekurencyjna, tzn. każdy element ciągu jest definiowany za pomocą jakichś innych elementów tego samego ciągu. - enedil 2019-01-12 13:41
W kwestii n, miało być oczywiście i, tylko się zagapiłem. - enedil 2019-01-12 13:43
Ok, czyli, żeby to dawało ten szereg, to musi być: taylor(0, x) = 1. Ale szczerze mówiąc nie widze związku tej relacji z szeregiem Taylora dla inkryminowanej funkcji... - lion137 2019-01-12 13:53

Pozostało 580 znaków

2019-01-12 15:23
1

Zamieniając i + 1 na i, i automatycznie i na i - 1 i zatrzymując rekurencje na i = 2 (wtedy zeruje się mianownik, więc dalsze liczenie nie ma sensu), zaimplenetowałem tę relację, ale nie wiem jak zinterpretować jej wyniki:

double taylor2(unsigned long i, double x) { // for i >= 2
    if (i == 2) return -0.125D * x * x;
    return (-0.25) * ( (2 * i - 3) * (2 * i - 4)  / (i * (i - 2)) * (x + 1) ) * taylor2(i - 1, x);  
}

int main () {
    std::cout << taylor2(4, 1.0D) << "\n"; // -> 0.125 ??
    std::cout << taylor(4, 1.0D) << "\n"; // - > 0.0625 OK czwarty współczytnnik szeregu

    return 0;
}

Pozostało 580 znaków

2019-01-12 16:03
1

To może najpierw popraw wzór - zamień tę linijkę

    return (-0.25) * ( (2 * i - 3) * (2 * i - 4)  / (i * (i - 2)) * (x + 1) ) * taylor2(i - 1, x);  

na taką

    return (-0.25) * ( (2 * i - 3) * (2 * i - 4)  / (i * (i - 2)) / (x + 1) ) * taylor2(i - 1, x);  

Pozostało 580 znaków

2019-01-12 18:30
1

Upierałbym się, że to nie jest to samo co we wzorze (jak jest wszystko przez (1 + x), / (1 + x), to dla mnie jest to samo, co 1 + x wchodzące do mianownika); nieważne, zmieniłem, ale dalej nie wiem co to zwraca:

double taylor2(unsigned long i, double x) { // for i >= 2
    if (i == 2) return -0.125D * x * x;
    return (-0.25) * ( (2 * i - 3) * (2 * i - 4)  / (i * (i - 2)) / (x + 1) ) * taylor2(i - 1, x);  
}

int main () {
    std::cout << taylor2(4, 1.0D) << "\n"; // -> -0.0078125 ???
    std::cout << taylor(4, 1.0D) << "\n"; // - > -0.0390625 OK, czwarty wspólczynnik szeregu.
    return 0;
}

Tak, umiem operować na ułamkach. U Ciebie mnożenie było już poza mianownikiem. - enedil 2019-01-12 19:42
I masz też rację, że coś jest nie tak, ale nie mam czasu debugować. - enedil 2019-01-12 19:42

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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