Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C] cosinus rozwijany w szereg Maclaurina

Ostatnio zmodyfikowano 2013-11-14 10:59
Autor Wiadomość
robek210
Temat założony przez niniejszego użytkownika
[C] cosinus rozwijany w szereg Maclaurina
» 2013-11-13 15:27:27
Witam wszystkich,
Na samym początku zaznaczę, że dopiero uczę się programować. Otóż próbuję napisać program w C wyznaczający wartość funkcji trygonometrycznych cos z rozwinięcia w szereg Maclaurina - wzór: http://tiny.pl/qtlds

Dane wejściowe:
1. xp - dolna granica zmiennej x
2. xk - górna granica zmiennej x
3. krok - z jakim następuje powiększanie x
4. dokładność obliczeń w procentach - ograniczająca liczbę wyrazów szeregu potęgowego

Po dość długim kombinowaniu udało mi się stworzyć poniższy kod ale nie mam pojęcia jak wstawić dokładność. Dodatkowo dla wartości x=>42 program wypisuje nierealne wartości cosinusa co może ma coś wspólnego właśnie z brakiem tej dokładności... Byłbym bardzo wdzięczny gdyby ktoś znalazł chwilę i pomógł
Program pisany za pomocą CodeBlocks'a

C/C++
#include<stdio.h>
#include<math.h>
int main()
{
    float xp, xk, krok;
    int z;
    printf( "Podaj poczatkowa liczbe xp:\n" );
    scanf( "%f", & xp );
    printf( "Podaj koncowa liczbe xk:\n" );
    scanf( "%f", & xk );
    printf( "Podaj krok z jakim ma nastepowac powiekszenie x:\n" );
    scanf( "%f", & krok );
    z =( xk - xp ) / krok; // Liczba wyrazów szeregu
   
    double cos1, wyr, x, lp; // cos1 - zmienna posiadająca aktualną wartoś cosx, wyr- zmienna posiadająca wartośc aktualnie liczonego wyrazu
    x = 0; // lp - zmienna pozwalajaca na wypisanie x + n*krok
    int i, j, n;
   
    printf( "Wartosc x: \t" "Wartosc cosx:\n" );
    for( x = xp, j = 0; j <= z; ++j ) // j-zmienna zapewniajaca liczbe wyrazow "z" szeregu
    {
       
        lp = x;
        cos1 = 1;
        wyr = 1;
       
        for( i = 2; i <= n; ++i ) // i-zmienna do liczelia silni w mianowniku
        {
           
            wyr = wyr *((( - 1 ) * x * x ) /(( 2 * i - 3 ) *( 2 * i - 2 ) ) ); //obliczanie biezacego wyrazu szeregu
           
            cos1 = cos1 + wyr; //dodawanie biezacego wyrazu do szeregu
           
        }
       
       
       
        printf( "%5.2lf                        %5.2lf               \n", lp, cos1 );
       
        x = lp + krok;
       
    }
    return 0;
}
P-96192
docentpp
» 2013-11-13 16:23:55
We wzorze McLaurina dokładność obliczeń zależy od ilości zsumowanych wyrazów.
Zależy więc od n , a nie od xp,xk.............

Przynajmniej ja tak interpretuję ten wzór. :-)
P-96197
robek210
Temat założony przez niniejszego użytkownika
» 2013-11-13 16:37:56
Też tak mi się wydaje i właśnie tu jest problem. Nie wiem w jaki sposób na podstawie wprowadzonej dokładności ograniczyć liczbę wyrazów szeregu...
P-96199
docentpp
» 2013-11-13 17:19:45
To jest ciąg szybko zbieżny,więc np. eps=dokładność ,
można porównywać z kolejno wyliczanymi elementami szeregu,
i jeśli kolejny wyraz jest mniejszy niż eps,
to osiągnie się zakładaną dokładność.

P-96202
robek210
Temat założony przez niniejszego użytkownika
» 2013-11-13 18:00:04
Chyba nie do końca o to chodzi
C/C++
...
for( i = 2; i <= n; ++i ) // i-zmienna do liczelia silni w mianowniku

{
   
    wyr = wyr *((( - 1 ) * x * x ) /(( 2 * i - 3 ) *( 2 * i - 2 ) ) ); //obliczanie biezacego wyrazu szeregu
   
    cos1 = cos1 + wyr; //dodawanie biezacego wyrazu do szeregu
   
}

if( cos1 <= epsilon )
{
   
   
    printf( "%5.2lf                        %5.2lf               \n", lp, cos1 );
}
x = lp + krok;

}
return 0;
}
Jak próbowałem porównywać z "wyr" to wychodziły strasznie kosmiczne wyniki, a tu po prostu sprawdza czy dana wartść cosinusa jest mniejsza od podanego ułamka ( zrobiłem epsilon=epsilon/100 żeby zamienić procenty na ułamki)
P-96206
docentpp
» 2013-11-13 19:01:55
Najłatwiej będzie znaleźć błąd jeśli przeredagujesz swój kod
do pojedynczej funkcji,do postaci wyliczającej
 cosinus wg McLaurina z określoną
ilością wyrazów,bez rozpatrywania dokładności.
Czyli :

C/C++
double cosinusMcL( double x, int k )
{
   
   
    // tutaj kod wyliczający
    //wartość funkcji cosinus
    //dla podanego x, dla k iteracji
    // bez wyznaczania dokładności obliczeń
   
   
}
 

Potem wstaw do wywołania funkcji
np x=0.23 , k=30 ;
np x=0.23 , k=50 ;

i porównaj z wartościami tabelarycznymi,
co da odpowiedź,czy twój algorytm i kod są prawidłowe.

Powtarzam, ciąg jest
mocno zbieżny.......

P-96210
docentpp
» 2013-11-14 00:36:30
Napisałem takie rozwiązanie :
C/C++
float cosinus( float x, int n )
{
    float l, // licznik
    d, // dzielnik
    xx, // oszczednosc obliczen
    wyr;
   
    l = 1.0;
    d = 1.0;
    xx =- x * x;
    wyr = 1.0;
   
    for( int i = 2; i <= n; ++i )
    {
        l *= xx;
        d *= 1.0 *( 2 * i - 3 ) *( 2 * i - 2 );
        wyr = wyr +( l / d );
    }
    return wyr;
}

Przetestowałem dla różnych x,n.

Już dla n=6 wyniki są porównywalne ze standardowym
cosinusem z biblioteki <math.h> //  float sin(float x)
Uzywam Dev 4.9.

Dokładność  obliczeń eps należy porównywać z wartością bezwzględną kolejnego
wyrazu ciągu McLaurina.

P-96242
robek210
Temat założony przez niniejszego użytkownika
» 2013-11-14 10:41:17
Zmodyfikowałem Twój kod (nie wiem oczywiście czy w dobry sposób) na potrzebę zadania i program nie wypisuje kompletnie nic...

C/C++
#include<stdio.h>
#include<math.h>
int main( void )
{
    float xp, xk, krok, epsilon, x;
    int z, j;
    printf( "Podaj poczatkowa liczbe xp:\n" );
    scanf( "%f", & xp );
    printf( "Podaj koncowa liczbe xk:\n" );
    scanf( "%f", & xk );
    printf( "Podaj krok z jakim ma nastepowac powiekszenie x:\n" );
    scanf( "%f", & krok );
    printf( "Podaj dokladnosc w procentach ograniczajaca liczbe wyrazow szeregu:\n" );
    scanf( "%f", & epsilon );
    epsilon = epsilon / 100;
    z =( xk - xp ) / krok; // Liczba elementów do wypisania
   
   
   
    float cosinus( float x, int n )
    {
        float l, // licznik
        d, // dzielnik
        xx, // oszczednosc obliczen
        wyr;
       
        l = 1.0;
        d = 1.0;
        xx =- x * x;
        wyr = 1.0;
        int i;
        x = xp;
        for( j = 0; j <= z; ++j )
        {
           
            for( fabs( wyr ) <= epsilon, i = 2; i <= n; ++i )
            {
                l *= xx;
                d *= 1.0 *( 2 * i - 3 ) *( 2 * i - 2 );
                wyr = wyr +( l / d );
               
            }
           
            printf( "%5.2lf                        %5.2lf               \n", x, wyr );
            x = x + krok;
           
        }
    }
    return 0;
}
P-96246
« 1 » 2
  Strona 1 z 2 Następna strona