Rozwinięcie w szereg ln(x)

0

Tablicowanie funkcji w zadanym przedziale, z zadaną liczbą
podprzedziałów, z wykorzystaniem rozwinięcia w szereg.
Dane wejściowe do programu: przedział, w którym funkcja ma
być tablicowana, liczba podprzedziałów
Podobnie jak w programie, który robiliśmy na zajęciach, a
dostępnym jako dokument programy3 na tej stronie trzeba
napisać funkcję szereg, która na podstawie rozwinięcia w
szereg oblicza wartość funkcji dla danego argumentu.
Na ekranie mają się pojawić 3 kolumny liczb: argument (x),
wartość funkcji z biblioteki matemtycznej dla x, wartość
funkcji szereg dla x.
W funkcji szereg nie uŜywamy funkcji pow ani silnia; do
obliczenia kolejnego wyrazu szeregu wykorzystujemy wyraz
poprzedni

tak wygląda szereg
ln x = (x-1)/x + (x-1)^2/(2x^2) + (x-1)^3/(3x^3) +....
x>0.5

Co mogę zmienić żeby było dobrze? Psycha juz siada.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define n 100
/*

ln x = (x-1)/x  + (x-1)^2/(2*x^2) + (x-1)^3/(3*x^3) +....


x>0.5

 */
double szereg(double x)
{
    double s, w;
    int i;
    s = x;
    w = x;
    for (i = 1; i < n; i++)
    {
        w = (w * (x-1)) / (i * i * x ) ;
        s = s + w;
    }
    return s;

}

int main()
{
    int lp;
    double a, b, krok, x;
    do
    {
        printf("podaj konce przedzialow i liczbe podprzedzialow\n");
        scanf("%lf %lf %d", &a, &b, &lp);
    } while (a <= 0.5 || b <= 0.5);

    krok = (b - a) / lp;
    printf("krok=%6.2lf\n\n\n", krok);
    printf(" ----------------------------\n");
    printf("      x  szereg(x)  ln(x)\n----------------------------\n");
    for (x = a; x <= b; x += krok)
        printf("%10.2lf %7.4lf %7.4lf\n", x, szereg(x), log(x));
    printf(" ----------------------------\n\n");
    return 0;
}
1

jak chcesz to zrobić na forach to musisz użyć dwóch pętli. Jedna która będzie obliczać cały element szeregu czyli to (x-1)^i/x^i*x^i...
a wewnątrz druga w której będziesz liczył mianownik czyli to: x^i *x^i ...i razy.

0
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define n 100
/*

ln x = (x-1)/x  + (x-1)^2/(2*x^2) + (x-1)^3/(3*x^3) +....


x>0.5

 */
double szereg(double x)
{
    double s, w, mian;
    int i;
    int j;
    s = x;
    w = x;
    mian = x;
    for (i = 1; i < n; i++)
    {
        for(j = 1; j < n; j++){
            mian = x * j * j;
            mian = s + mian;
        }
        w = (w * (x-1)) / mian ;
        s = s + w;
    }
    return s;

}

int main()
{
    int lp;
    double a, b, krok, x;
    do
    {
        printf("podaj konce przedzialow i liczbe podprzedzialow\n");
        scanf("%lf %lf %d", &a, &b, &lp);
    } while (a <= 0.5 || b <= 0.5);

    krok = (b - a) / lp;
    printf("krok=%6.2lf\n\n\n", krok);
    printf(" ----------------------------\n");
    printf("      x  szereg(x)  ln(x)\n----------------------------\n");
    for (x = a; x <= b; x += krok)
        printf("%10.2lf %7.4lf %7.4lf\n", x, szereg(x), log(x));
    printf(" ----------------------------\n\n");
    return 0;
}

O to chodzi ?

3

Jak podzielisz drugi wyraz przez pierwszy to otrzymasz (x-1)/2x, jak podzielisz trzeci przez drugi to otrzymasz 2(x-1)/3x, ogólnie każdy następny wyraz jest iloczynem poprzedniego oraz wyrażenia (x-1.0)*(i-1) / (i * x). Proponuję coś takiego:

double szereg(double x)
{
    double s, w;
    int i;
    s = (x-1.0)/x;
    w = 1.0;
    for (i = 2; i < n; i++)
    {
        w = w * (x-1.0)*(i-1) / (i * x) ;
        s = s + w;
    }
    return s;
}
1
jow12 napisał(a):

tak wygląda szereg
ln x = (x-1)/x + (x-1)^2/(2x^2) + (x-1)^3/(3x^3) +....
x>0.5

Coś pomieszałeś.
Najprawdopodobniej masz kolizję oznaczeń i nie zauważyłeś, że jest x oraz x0 czyli odpowiednio argument szeregu i stała reprezentująca punkt w okół którego rozwija się w szereg Taylora.

https://www.wolframalpha.com/input?i=taylor+log%28x%29+at+x%3D1
log(x) = (x - 1) - 1/2 (x - 1)^2 + 1/3 (x - 1)^3 - 1/4 (x - 1)^4 + O((x - 1)^5)


Po zastosowaniu się do poprawnego wzoru wszystko działa:

double log_series(double x, int n = 100)
{
    const double dx = -(x - 1.0);
    double powXI = -1;
    double sum = 0;

    for(int i = 1; i < n; ++i) {
        powXI *= dx; 
        sum += powXI/i;
    }

    return sum;
}

https://godbolt.org/z/dn1jraoP8

Pamiętaj, też że jest coś takiego jak promień zbieżności szeregu (tutaj 1), więc poza pewnym zakresem szereg wybuchnie w nieskończoność.

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