background image

Politechnika Śląska   

 

 

 

 

 

 

                   

          Gliwice 

Wydział Automatyki, Elektroniki i Informatyki                        

 

Rok akademicki 2008/2009 

Kierunek: Automatyka i Robotyka sem.4                                                           

            Semestr letni 

 

 

 

 

 

Metody Numeryczne 

Laboratorium 

 

 

Ćw. 6: Aproksymacja 

 

 

 

Wykonali: 

                                                                                                               Tomasz LITWIN, 

       Bartosz GUDOWSKI 

                                                                                                                  Grupa 3, sekcja 1 

                                                                                                       Data odbycia ćwiczenia: 

                                                                                                                             24.04.2009r. 

 

 

 

background image

 

1.  Aproksymacja średniokwadratowa z użyciem wielomianów ortogonalnych: 

Opis metody: 

Daną funkcję 

]

,

[

 

  

)

(

2

b

a

L

x

f

p

 należy aproksymować z wagą 

)

(x

p

funkcją 

)

(x

q

o postaci : 

=

=

=

n

i

i

i

i

x

c

x

q

0

)

(

)

(

ϕ

 

gdzie: 

)

(x

i

ϕ

]

,

[

 

2

b

a

L

p

n

i

 

...,

 

,

1

 

,

0

=

 są funkcjami tworzącymi układ ortogonalny w 

]

,

[

 

2

b

a

L

p

, tzn. 

=

=

b

a

j

i

dx

x

x

x

p

j

i

   

dla

const  

j

i

    

dla

   

0

     

)

(

)

(

)

(

ϕ

ϕ

 

Miara odległości pomiędzy funkcjami jest zdefiniowana wzorem: 

=

b

a

dx

x

f

x

q

x

p

D

2

)]

(

)

(

)[

(

 

Współczynniki 

i

 wyznaczamy z następującego wzoru (

n

i

 

...,

 

,

1

 

,

0

=

): 

=

b

a

i

i

i

dx

x

f

x

x

p

c

)

(

)

(

)

(

1

ϕ

λ

 

gdzie: 

=

b

a

i

i

dx

x

x

p

)

(

)

(

2

ϕ

λ

 

Otrzymane w programie wielomiany: 

1 stopnia: y = 0.841471 

2 stopnia: y = 0.465261x

2

 + 0.996558 

3 stopnia: y = 0.465261x

2

 + 0.996558 

4 stopnia: y = 0.0039554375x

4

 + 0.43135725x

2

 + 0.999948375 

5 stopnia: y = 0.0039554375x

4

 + 0.43135725x

2

 + 0.999948375 

 

 

background image

 

Wynik działania programu: 

 

2.  Metoda najmniejszych kwadratów(aproksymacja punktowa) 

Opis metody: 

Funkcję f(x) podaną w (n+1) punktach dyskretnych  , (i=0,1,…,n) należy aproksymować wielomianem 

potęgowym o postaci: 

 

gdzie m-stopień wielomianu aproksymującego (m<n). 

Poszczególne niewiadome 

 otrzymujemy rozwiązując układ równań

Otrzymane w programie wielomiany: 

1 stopnia: y = 1,8-0,4x 

2 stopnia: y = 1,514286-0,4x+0,142857

 

3 stopnia: y = 1,514286-1,25x+0,142857

+0,25

 

4 stopnia: y = 4-1,25x-5,208333

+0,25

+1,208333

 

background image

Wynik działania programu 

 

3.  Wnioski: 

Wielomiany o stopniu powyżej trzeciego odwzorowują niemal idealnie przebieg funkcji w metodzie 

aproksymacji średniokwadratowej. Przy stopniu wielomianu aproksymującego równym 2 i 3 można 

jeszcze zauważyć„gołym okiem” różnice w przebiegu badanej funkcji i wielomianu aproksymującego ją. 

W metodzie najmniejszych kwadratów widoczny jest wzrost dokładności aproksymacji wraz ze 

zwiększaniem stopnia wielomianu aproksymującego. Dla maksymalnego stopnia wielomianu 

aproksymującego jaki mogliśmy zastosować mając funkcję daną w pięciu punktach wielomian ten jest 

jednocześnie wielomianem interpolacyjnym co doskonale widać na dołączonym wykresie. 

4.  Kody programów: 

a)  Aproksymacja średniokwadratowa  

#include

 

<stdio.h> 

#include

 

<stdlib.h> 

#include

 

<math.h> 

 

double

 funka(

double

 x) 

return

 cos(x); 

//funkcja do aproksymacji 


 
 

background image

double

 legendre(

double

 x, 

int

 n, 

int

 opcja) 

int

 i; 

double

 Pn[10]; 

 
   Pn[0] = 1; 
   

for

(i = 0; i <= n; i++) 

   { 
      Pn[i+1] = ((2*i+1)*x*Pn[i]-i*Pn[i-1])/(i+1); 
   } 
    

if

(opcja == 1) 

return

 pow(Pn[n],2); 

if

(opcja == 2) 

return

 (Pn[n]*funka(x)); 

if

(opcja == 3) 

return

 Pn[n]; 


 

//simpson 

double

 simpson(

double

 wezly[], 

double

 h, 

int

 ile_wezlow, 

int

 n, 

int

 opcja) 

int

 i; 

double

 suma = 0; 

 
  

for

(i = 0; i <= (2*ile_wezlow); i++) 

   { 
   

if

(i == 0 || i == (2*ile_wezlow)) suma += legendre(wezly[i],n,opcja); 

   

else

      

if

(i%2 == 0) suma += 2*legendre(wezly[i],n,opcja); 

      

if

(i%2 != 0) suma += 4*legendre(wezly[i],n,opcja); 

      } 
   } 
suma = (h/3.0)*suma; 

return

 suma; 


 

int

 main() 

int

 n, i, ile_wezlow = 17; 

double

 j, a = -1, b = 1, h, wezly[50]; 

double

 lambda[10], wsp_c[10], wynik; 

 

//wyznaczanie wezlow do metody simpsona 

h = (b-a)/(2*ile_wezlow); 
   

for

(i = 0; i <= (2*ile_wezlow); i++)  

   { 
      wezly[i] = i*h + a;     
   } 
  
 
printf(

"Podaj n: "

); 

scanf(

"%d"

, &n); 

 
   

//wyznaczanie wsp lambda (opcja simpson = 1) oraz wsp_c (opcja simpson = 2) 

   

for

(i = 0; i <= n; i++) 

   { 
      lambda[i] = simpson(wezly,h,ile_wezlow,i,1); 
      wsp_c[i] = simpson(wezly,h,ile_wezlow,i,2)/lambda[i]; 
      printf(

"lambda[%d] = %lf\n"

,i,lambda[i]); 

      printf(

"wsp_c[%d] = %lf\n"

,i,wsp_c[i]); 

   } 
 
   

//wynik, wartosci pktow funkcji aproksymujacej

 

FILE *out; 
out = fopen(

"wynik.txt"

,

"wt"

); 

   

for

(j = -1; j <= 1; j+=0.1) 

//przedzial wartosci 

   { 
      wynik = 0; 
      

for

(i = 0; i <= n; i++) 

background image

      { 
         wynik += wsp_c[i]*legendre(j,i,3); 
      } 
      fprintf(out,

"%lf,\n"

,wynik); 

   } 
fclose(out); 
system(

"pause"

); 

return

 0; 

 

b)  Metoda najmniejszych kwadratów 

#include

<stdio.h> 

#include

<math.h> 

#include

<stdlib.h> 

 

int

 main() 

double

 x[5]={-2,-1,0,1,2} , y[5]={3,1,4,-1,2}, S[9]={0}, T[9]={0}, a[9][9]={0}, 

z[9]={0},roznica=0; 

int

 n=4,m,k,i,j; 

 
printf(

"Podaj stopien wielomianu aproksymujacego\n"

); 

scanf(

"%d"

,&m); 

 

// obliczanie wartosci S 

for

(k = 0; k <= 2*m; k++) 

{          
   

for

(i = 0; i <= n; i++) 

   { 
       S[k]+=pow(x[i],k);  
   } 

//   printf("S[%d] = %lf\n",k,S[k]); 

}    
 

// obliczanie wartosci T 

for

(k = 0; k <= m; k++) 


   

for

(i = 0; i <= n; i++) 

   { 
       T[k]+=pow(x[i],k)*y[i]; 
   } 

//   printf("T[%d] = %lf\n",k,T[k]); 


 

// stworzenie ukladu rownan 

for

( j = 1;j <= m+2;j++) 


    

for

( i = 1;i <= m+1;i++) 

    { 
        

if

(j <= m+1) 

           a[i][j]=S[i+j-2]; 
        

if

(j == m+2) 

           a[i][j] = T[i-1]; 

// 

 

 

 

printf("Rownanie %lf\n",a[i][j]); 

 

 

 

 

 

//rozwiazanie ukladu rownan metoda Gaussa 

n = m+1; 

for

 ( i = 1; i <= n; i++) 


   

for

 (j = n+1; j >= i; j--) 

   { 
 

 

 

a[i][j] = a[i][j] / a[i][i]; 

   } 
 

background image

      

for

 (k = i+1; k <= n; k++) 

      { 
         

for

 (j = n+1; j >= i; j--) 

         { 
 

 

 

 

a[k][j] -= a[i][j] * a[k][i]; 

          } 
       } 
}    
roznica; 

for

(k = n;k >= 1;k--) 


    

for

(i = n-1;i >= k;i--) 

       { 

 

        roznica+=a[k][i+1]*z[i+1]; 
       } 
 

z[k] = a[k][n+1]-roznica; 

 

printf(

"Wspolczynnik a[%d] = %lf\n"

,k-1,z[k]); 

 

roznica=0; 


system(

"pause"

); 

return

 0;