Interpolacja Lagrange'a

0

Może mi ktoś powiedzieć czemu ten kawałek kodu nie oblicza tego co trzeba????

..q:kod usuniety na zyczenie autora..

po wprowadzeniu wartości wyświetla się takie coś:
w[000000] wynosi

Oczywiście to jest część programu! Reszta działa prawidłowo! Z góry dzięki za podpowiedz

0

Po 1: Na forum mamy takie coś jak kolorowanie składni.
Po 2: A co to jest a, y, x, p, b,w? Skąd wiesz, że reszta zdiała jak należy? W jaki sposób wypisujesz wynik? Daj więcej kodu, Wiele razy mówione było, że nie jesteśmy jasnowidzami.
Po 3: Po kiego grzyba wysyłasz drugiego posta po 2 minutach?

0

więcej nie wyśle bo pozniej kazdy bedzie kopiował , float w, p, a[10], b[10], x[10], y[10], zmienne typu float

0

jakbys znał co to jest interpolacja Lagrange'a to bys wiedzial o co chodzi, kod który umieścilem wyzej jest odzwierciedleniem wzrou Lagrange'a, chyba ze zle cos napisalem.
oto wzór: http://www-users.mat.uni.torun.pl/~piwosz/strony/15.htm

/* Tak, po tym jak nowa kopia tego tematu wylądowała w koszu ktoś dostał rozdwojenia jaźni chyba zupełnie...

BOBIk - 89.228.40.166 (host-89-228-40-166.elk.mm.pl, ) Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.8.1.12) Gecko/20080201 Firefox/</li> BUDI - 89.228.40.166 (host-89-228-40-166.elk.mm.pl, ) Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.8.1.12) Gecko/20080201 Firefox/
*/ // deus
</li> </ul>
0

Kopiował kod napisany tak nieczytelnie jak ten? No way! Juź prościej byłoby napisać wszystko od zera. A jeśli oczekujesz pomocy NAPRAWDĘ wyślij więcej kody, bo błąd moźe kryć się gdzie indziej.

0

dodałem drugi post bo myslalem ze nie został opublikowany, a można to pozniej usunąć z forum ten cały post po wyjaśnieniu problemu??? to jest cały program:

..q:kod usuniety na zyczenie autora..
0

tu masz jeden błąd:

printf("w[%p] wynosi ""\n",w);

%p oznacza przekazywanie wskaźnika, a nie wyniku typu float. popatrz tu.

0

Dodatkowo, nie sprawdzasz, czy n jest mniejsze od 10, co może spowodować wyjście poza zakres, a co za tym, idzie spektakularne wywalenie programu.

0

To jak mogłoby byc prawidłowo?? Mógłbyś wprowadzić małą modyfikacje?? BUDI

// 89.228.40.166 (host-89-228-40-166.elk.mm.pl, ) Mozilla/5.0 (Windows; U; Windows NT 5.1; pl; rv:1.8.1.12) Gecko/20080201 Firefox/

zaczyna mnie to nudzić, trzeci nick w przeciągu 6 godzin... tak bardzo Ci zależy? Daj ogłoszenie w dziale Praca. * deus </li> </ul>
0
..q:kod usuniety na zyczenie autora..

Z printf/scanf Ci nie pomogę, ponieważ wolę cout/cin (czytelniejszy zapis, odrobinę wolniejsze)

0

@Its not me:
Człowieku uparłeś się na obsługiwanie błędów, a i tak nie obsłużyłeś wszystkich (co z <=1). Pamiętaj, że to jest początkujący i on przechodzi fazę "ma działać" (dawać dobry wynik). Każdy od takiego podejścia zaczynał, a dopiero potem kolejne poziomy wtajemniczenia: "powinno/musi być efektywne" i "musi być niezawodne".
Więc pomijając poprawki obsług błędów ja bym napisał to tak (zresztą przeglądając twój algorytm mam spore wątpliwości czy robi to co powinien - przepisałeś od BUDI bez zastanowienia):

#include <cstdio>
#include <cstdlib>

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

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

double LagrangeInterp(double x, const double x0[], const 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;
}

int main (void)
{
        int n,i;
        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);

        printf("w(%f) wynosi %f\n", x, LagrangeInterp(x,x0,y0,n));
        system("pause");
}

Przyznaje, że nie jest to rozwiązanie optymalne bo można pewne wartości "zwinąć" do y0, ale nie chciało mi się tego robić (człon y0[i]/(DifProduct(x0[i],x0,i)*DifProduct(x0[i],x0+i+1,n-i)) jest stały przy tych samych punktach wejściowych a różnych x).

0

Marku jest troche lepiej ale dalej podaje zły wynik, ale dzięki za pomoc:), troszkę błędów zrobiłeś ale reszta ok, ale dalej nie wiem co z tym zrobic P

0

@Marek
Dziwne... ja uczyłem się pisać tak, aby było bez błędów i działało, potem na efektywności się skupiłem. Algorytmu nie przeglądałem, bo nie wiem nawet co on ma robić, nie chciało mi się sprawdzać. A poza tym, pętla przy n <= 0 nie wykona się ani razu, więc nie ma sensu tego sprawdzać. A to co ty tam wyprawiasz, nie powinno W OGÓLE być przepuszczone przez kompilator:

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

To NIE MA PRAWA działać. Tablice w ten sposób można tworzyć tylko, jeśli n jest znane w czasie kompilacji. W tym przypadku powinno to być napisane tak:

int n,i;
double x;
double *x0;
double *y0;
printf ("Podaj ilosc elementow: ");
scanf ("%d", &n);
x0 = new (std::nothrow) double[n];
    if(!x0)
      {
      return 0;
      }
y0 = new (std::nothrow) double[n];
    if(!y0)
      {
      delete [] x0;
      return 0;
      }
//reszta maina
if(x0)
      {
      delete [] x0;
      x0 = NULL;
      }
if(y0)
      {
      delete [] y0;
      y0 = NULL;
      }
0

Jak to "double x0[n], y0[n];" napisałem to też się zdziwiłem, że kompilator to łyknął (MinGW), ale jak puściłem to przez Borlanda to już się tak nie dało.

0

gcc i mingw jak pracuja w trybie "C" to puszczaja, poniewaz w C99 taka konstrukcja jest dozwolona. mechanizm tworzenia tablicy na stosie i tak jest parametryzowany rozmiarem, wiec dziwie sie ze takie ograniczenie wprowazono kiedys w ogole.. natomiast w "C++" tego NIE MA i KOMPILATOR C++ tego nie pusci. dodaj do opcji mingwa zgodnosci ze standardem i zobaczysz :)

0
schlesser napisał(a)

Marku jest troche lepiej ale dalej podaje zły wynik, ale dzięki za pomoc:), troszkę błędów zrobiłeś ale reszta ok, ale dalej nie wiem co z tym zrobic P

Nie wiem jakie błędy masz na myśli, pewnie pomyliłem string formatujący (preferuje iostream), pewnie zamiast '%f' powinno być '%e'.
W każdym razie zrobiłem na chybcika generujący (prawie) przypadkowe punkty i narysowałem interpolację wykonaną moimi funkcjami i wygląda to dobrze. Interpolacja biegnie przez wszystkie punkty wejściowe tak jak powinna.
Będę wdzięczny za wskazanie gdzie widzisz te błędy (czegoś się nauczę) :-) .

0

Wszystko ładnie pięknie ale program dalej nie wykonuje tego co trzeba, kompiluje sie owszem ale dalej wynik wyskakuje: w[0.0000000] wynosi

problem w tym ze podawac np: w[2] wynosi 20

o to chodzi, zeby to napisac jak najprosciej za pomoca najprostszych komend i polecen!

0

Nienawidzę scanf i printf. Pod doczytaniu dokumentacji: tam gdzie jest scanf zamiast "%f" ma być "%lf" lub "%le". Printf bez zmian!
Sam algorytm jest poprawny.

0

Właśnie dlatego wolę cin/cout, nie trzeba się bawić w te głupie znaczniki, jedyną ich bolączką jest to, że bez wyłączenia synchronizacji są strasznie wolne.

0

Zrobilem Marek tak jak mowiles ale dalej nie dziala tak jak trzeba:]

0

Możesz być bardziej konkretny? Nie jestem jasnowidzem.
Próbowałeś to debugować?

0

Hallo BUDI!

zainteresowal mnie ten temat i dlatego postanowilem zaproponowac Ci nastepujace rozwiazanie
(quick & dirty ;-) ):

int _tmain(int argc, _TCHAR* argv[])
{
	int x, n, tab[4][2], i, k;
	double wartosc, iloczyn;

	n  = 4;				               // ilosc punktow

	tab[0][0] = 0;					// wspolrzedne punktu 1 ( 0, 0)
	tab[0][1] = 0;			

	tab[1][0] = 2;					// wspolrzedne punktu 2 ( 2, 4)
	tab[1][1] = 4;

	tab[2][0] = 3;					// wspolrzedne punktu 3 ( 3, 9)
	tab[2][1] = 9;										

	tab[3][0] = 5;					// wspolrzedne punktu 4 ( 5,25)
	tab[3][1] = 25;			

	x = 4;					        // wspolrzedna x punktu, w ktorym 
                                                              // nalezy znalesc wartosc funkcji

	// Poniewaz dla latwiejszego sprawdzenia wyniku, rozmyslnie tak dobralem
	// punkty, aby lezaly na paraboli y = x^2, tak wiec wartosc funkcji w punkcie
	// o wspolrzednej x = 4 powinna wynosic 16. 

	// inicjalizacja
	wartosc = 0;
	cout << wartosc << endl;

	// metoda Lagrange'a
	for (i = 0; i < n; i++) 
	{
		iloczyn = 1;

		for (k = 0; k < n; k++)
		{
			if (k != i)
			{
				iloczyn = iloczyn * (x - tab[k][0])/(tab[i][0] - tab[k][0]);
			}			            
		}

		wartosc = wartosc + tab[i][1] * iloczyn;
	}

	// wyswietlenei wyniku na ekranie
	cout << wartosc << endl;

	system("PAUSE");

	return 0;
}

Pozdrawiam
Markus

0

Dzieki za odpowiedzi, ale i tak z nich nie skorzystalem, wlasnie przed chwila doszedlem jak to zrobic, byly tylko 2 malutkie błędy w ostatnim printf :] a tyle zamieszania sie zrobilo wokół tego:), markus dobry program ale w c++. Uważam temat za zamknięty. Pozdrawiam zainteresowanych

0

Witam, chciałbym odświeżyć trochę temat ;-)

Wykorzystuje w swoim programie wyżej zaproponowany algorytm czyli:

// metoda Lagrange'a
for (i = 0; i < n; i++)
{
iloczyn = 1;

            for (k = 0; k < n; k++)
            {
                    if (k != i)
                    {
                            iloczyn = iloczyn * (x - tab[k][0])/(tab[i][0] - tab[k][0]);
                    }                                   
            }

            wartosc = wartosc + tab[i][1] * iloczyn;
    }

Jest to metoda 2punktowa (algorytm bierze punkt i jego dwóch najbliższych sąsiadów-węzły) i program się sypie na brzegach funkcji. Podobno, żeby to zlikwidować należy wziąć 4 bądź nawet 6 punktów... Czy ktoś wie jak przekształcić ten wzór??? siedzę nad tym 3 dni i nic nie mogę wymyślić ;// HELP ;-P

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