Skocz do zawartości

Intepolacja Wielomianu Metoda Newtona I Lagrange`a - Prośba O Weryfikację Poprawności Kodu


Jasiek_M

Rekomendowane odpowiedzi

Witam,

Napisałem taki o to programik:

#include <cstdio>
#include <cstdlib>

inline double DifProduct(double x,double x0[],int n)
{
   double result;

   result=1.0;
   for(int i=0;i<n;++i)
       result*=(x-x0[i]);
   return result;
}
double silnia( double n){
       if(n==0){
               return 1;
       }else{
               return n*silnia(n-1);
       }
}

double potega(double a, double  {
       double wynik = 1;
       for (int i = b; i > 0; i--) {
               wynik *= a;
       }
       return wynik;
}

double LagrangeInterp(double x,double x0[],double y0[],int n)
{
   double result,a;

   a = DifProduct(x,x0,n);
   n--; // uwaga! zmiejszenie n
   result = 0.0;
   for(int i=0;i<=n;++i)
   {
       if(x==x0[i])
           return y0[i];

       result += a*y0[i]/((x-x0[i])*DifProduct(x0[i],x0,i)*DifProduct(x0[i],x0+i+1,n-i));
   }
   return result;
}

double NewtonInterp(double x, double x0[], double y0[],int n)
{
int degree = n;
       double iloczyn;
       double wynik = 0;
       double h = x0[1] - x0[0];
       double ile;


       wynik = y0[0];
       for(int ile=1;ile<degree;ile++) {
           for(int j=0;j<(degree-ile);j++) {
               y0[j] = y0[j+1] - y0[j];
           }
           iloczyn = 1;
           for(int j=0;j<ile;j++) {
               iloczyn = iloczyn * (x - x0[j]);
           }
           wynik += (y0[0]*iloczyn)/silnia(ile)*potega(h, ile);
       }
       return wynik;
}

int main (void)
{
       int n,i,h;
       double x;

       printf ("Podaj ilosc elementow: ");
       scanf ("%d", &n);
       double x0[n], y0[n];

       for (i = 0; i < n; i++)
       {
               printf ("Podaj x[%d]: ", i);
               scanf ("%f", &x0[i]);
               printf ("Podaj y[%d]: ", i);
               scanf ("%f", &y0[i]);
       }
       printf ("Podaj wartosc x : ");
       scanf ("%f", &x);

       for(int i=0;i<n-1;i++) {
           if (i==0) {
               h = x0[i+1] - x0[i];
           }
           else {
               if (h!=(x0[i+1] - x0[i])) {
                   printf("Roznica miedzy poszczegolnymi X-ami nie jest stala - wybieram metode interpolacji Lagrange`a");
                   return LagrangeInterp(x,x0,y0,n);
               }
               else {printf("Roznica miedzy poszczegolnymi X-ami jest sta³a - wybieram metode interpolacji Newtona");NewtonInterp(x,x0,y0,n);}
           }
       }

       system("pause");
}

 

Niestety wynik jego działania przedstawia się następująco:

43355141.jpg

Wielokrotnie przeczesywałem kod w próbie znalezienia błędu i nic. Niestety sam sobie z tym nie poradzę więc proszę o pomoc lub chociaż naprowadzenie na właściwy trop...

Odnośnik do komentarza
Udostępnij na innych stronach

Oto moje uwagi do programu - może się przydadzą. Jeśli masz jakieś problemy to pisz co otrzymujesz a co powinieneś otrzymać.

 

double silnia( double n){
       if(n==0){
               return 1;
       }else{
               return n*silnia(n-1);
       }
}

Silnia obowiązuje liczby naturalne - double nie reprezentuje liczb naturalnych. Tak na marginesie to nie zaleca się przyrównywania double do 0.

 

double potega(double a, double  {
       double wynik = 1;
       for (int i = b; i > 0; i--) {
               wynik *= a;
       }
       return wynik;
}

Literówka w definicji. Pod wynik dałbym jednak 1.0 a nie 1 tak dla bezpieczeństwa(w końcu wynik ma być w double).

 

           else {
               if (h!=(x0[i+1] - x0[i])) {
                   printf("Roznica miedzy poszczegolnymi X-ami nie jest stala - wybieram metode interpolacji Lagrange`a");
                   return LagrangeInterp(x,x0,y0,n);
               }
               else {printf("Roznica miedzy poszczegolnymi X-ami jest sta³a - wybieram metode interpolacji Newtona");NewtonInterp(x,x0,y0,n);}
           }
       }

       system("pause");
}

Wstaw drukowanie wyniku na ekran, bo jedynie wynik jest zwracany przez aplikację.

Odnośnik do komentarza
Udostępnij na innych stronach

Hej,

wykonalem wszystkie rady Lukasz69, oto przerobiony kod:

#include <cstdio>
#include <cstdlib>

inline double DifProduct(double x,double x0[],int n)
{
   double result;

   result=1.0;
   for(int i=0;i<n;++i)
       result*=(x-x0[i]);
   return result;
}
int silnia( int n){
       if(n==0){
               return 1;
       }else{
               return n*silnia(n-1);
       }
}

double potega(double a, double  {
       double wynik = 1.0;
       for (int i = b; i > 0; i--) {
               wynik *= a;
       }
       return wynik;
}

double LagrangeInterp(double x,double x0[],double y0[],int n)
{
   double result,a;

   a = DifProduct(x,x0,n);
   n--; // uwaga! zmiejszenie n
   result = 0.0;
   for(int i=0;i<=n;++i)
   {
       if(x==x0[i])
           return y0[i];

       result += a*y0[i]/((x-x0[i])*DifProduct(x0[i],x0,i)*DifProduct(x0[i],x0+i+1,n-i));
   }
   printf("Wynik: %f",result);
   return result;
}

double NewtonInterp(double x, double x0[], double y0[],int n)
{
int degree = n;
       double iloczyn;
       double wynik = 0;
       double h = x0[1] - x0[0];
       double ile;


       wynik = y0[0];
       for(int ile=1;ile<degree;ile++) {
           for(int j=0;j<(degree-ile);j++) {
               y0[j] = y0[j+1] - y0[j];
           }
           iloczyn = 1;
           for(int j=0;j<ile;j++) {
               iloczyn = iloczyn * (x - x0[j]);
           }
           wynik += (y0[0]*iloczyn)/silnia((int)ile)*potega(h, ile);
       }
printf("Wynik: %f",wynik);
       return wynik;
}

int main (void)
{
       int n,i,h;
       double x;

       printf ("Podaj ilosc elementow: ");
       scanf ("%d", &n);
       double x0[n], y0[n];

       for (i = 0; i < n; i++)
       {
               printf ("Podaj x[%d]: ", i);
               scanf ("%f", &x0[i]);
               printf ("Podaj y[%d]: ", i);
               scanf ("%f", &y0[i]);
       }
       printf ("Podaj wartosc x : ");
       scanf ("%f", &x);

       for(int i=0;i<n-1;i++) {
           if (i==0) {
               h = x0[i+1] - x0[i];
           }
           else {
               if (h!=(x0[i+1] - x0[i])) {
                   printf("Roznica miedzy poszczegolnymi X-ami nie jest stala - wybieram metode interpolacji Lagrange`a");
                   return LagrangeInterp(x,x0,y0,n);
               }
               else {printf("Roznica miedzy poszczegolnymi X-ami jest sta³a - wybieram metode interpolacji Newtona");NewtonInterp(x,x0,y0,n);}
           }
       }

       system("pause");
}

Wynik pod Windowsem:

60209613.png

 

Wynik pod Linuxem:

[Jasiek@Jasiek Programowanie Metdy obliczeniowe]$ ./a.out

Podaj ilosc elementow: 6

Podaj x[0]: 0.35

Podaj y[0]: 2.73951

Podaj x[1]: 0.41

Podaj y[1]: 2.30080

Podaj x[2]: 0.47

Podaj y[2]: 1.96864

Podaj x[3]: 0.51

Podaj y[3]: 1.78776

Podaj x[4]: 0.56

Podaj y[4]: 1.59502

Podaj x[5]: 0.64

Podaj y[5]: 1.34310

Podaj wartosc x : 0.526

Roznica miedzy poszczegolnymi X-ami nie jest stala - wybieram metode interpolacji Lagrange`aWynik: -inf[Jasiek@Jasiek Programowanie Metdy obliczeniowe]$

 

Z Windowsem to przypadek ale mieliscie racje bo CodeBlocks wyrzuca mi takie warningi:

/media/621CC8761CC846AF/Programowanie/Metody/1/1/main.cpp|83|warning: format ‘%f’ expects argument of type ‘float*’, but argument 2 has type ‘double*’ [-Wformat]|

Nie wiem zbytnio tylko co z tym zrobic-wszedzie pisze ze "%f" moze byc tak samo do float jak i do double...

 

Ehhh normalnie zalamka, nie jestem wstanie tego naprawic a glowie sie i glowie...

Odnośnik do komentarza
Udostępnij na innych stronach

Debbugera uzywalem przy dalszych obliczeniach, ale uzycie go od poczatku faktycznie bylo dobrym pomyslem. Oto po wpisaniu wartosci tablic otrzymujemy taki kwiatek:

forumyx.png

wartosci tablic "x" i "y" w ogóle nie ulegly zmianie, dodatkowo program widzi dwie zmienne "i"-jedna dobra(wartosc taka jak ilosc przebiegów petli) a druga zainicjowana losowymi wartosciami. Zaraz jade na zajecia i juz raczej nie zdaze sie tym zajac, ale wieczorem spróbuje zobaczyc co moze isc zle...

 

 

Edit: Pozamiatane, scanf przyjmuje dla double "%lf" zamiast "f". Natrafilem tak po zmudnych poszukiwaniach bo prawie wszedzie pisze ze "%f" odnosi sie i do float i do double...

Odnośnik do komentarza
Udostępnij na innych stronach

Czyli problem tkwil w czytaniu wartosci? Co do zmiennych i to na poczatku programu deklarujesz pierwsza zmienna i - ona ma wartosc losowa(smieci z pamieci), poniewaz nie przypisales jej wartosci. Ogólnie to zmienne typu i, j, x, z, y to nadaja sie co najwyzej do liczników petli - zmienne trzeba nazywac konkretnie. Pózniej wrócisz do kodu i trzeba wiedziec co sie dzieje w programie.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
×
×
  • Dodaj nową pozycję...