Interpolacja

D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:13 dni
  • Postów:58
0

Napisałem sobie 100 punktów będących węzłami interpolacyjnymi funkcji. Następnie po zinterpolowaniu tych punktów i narysowaniu węzłów oraz wykresu funkcji zinterpolowanej okazało się że została poprawnie tylko na pewnym niedużym przedziale.
Ma ktoś podejrzenia czym może być to spowodowane?

Załączam plik z punktami. Funkcję liczącą wartości funkcji interpolowanej pobrałem gotową.

Kodu nie zamieszczam poniewaz jest raczej dobry. Korzystam z gotowej funkcji. Przy 10 punktach funkcja interpolowana jest dobrze. Nie wiem tylko jaki warunek nie jest spelniony przy tych moich danych ze na wiekszosci przedzialu wychodza duze bledy. Interpoluje na przedziale xe(0;600) a wykres jest rysowany poprawnie tylko dla ok (400;500). Reszta to bardzo duze liczby rzedu e15.

edytowany 2x, ostatnio: danielbr3
MarekR22
EEE... czego ty oczekujesz? Że ktoś ci przeanalizuje dane? Jeśli masz problem z kodem, to to pytanie wymaga bardziej interwencji wróżki, a nie programistów.
D3
Problem nie lezy w kodzie tylko raczej w założeniach interpolacji lagrange'a
MarekR22
to jest tylko twoje przekonanie.
TD
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 4 lata
  • Postów:380
0

Skąd wiesz ze wynik jest niepoprawny? Masz wzór funkcji która jest oczekiwanym rezultatem?

D3
Po narysowaniu wezlow i wykresu funkcji interpolowanej wykres tylko na przedziale (400;500) przechodzi przez te punkty a na pozostałych przedziałach wartosci odbiegaja znacznie od punktów (rzedu xE15) i w zadnym miejscu nawet sie do nich nie zblizaja.
D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:13 dni
  • Postów:58
0

Wykres:
czerwone to wezły, niebieskie funkcja po interpolacji

MO
  • Rejestracja:około 10 lat
  • Ostatnio:3 dni
  • Lokalizacja:Tam gdzie jest (centy)metro...
0

Wiesz co, programowanie to jednak dość prosta dziedzina. Ogólnie jeśli program "jest dobry" -> zwraca dobre wyniki. Jeśli program "nie zwraca dobrych wyników" -> program nie jest dobry.

Bez kodu to przypuszczenia, światopoglądy, interpretacje... wróżbiarstwo.


Każdy problem w informatyce można rozwiązać, dodając kolejny poziom pośredniości,z wyjątkiem problemu zbyt dużej liczby warstw pośredniości — David J. Wheeler
D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:13 dni
  • Postów:58
0
Kopiuj
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "winbgi2.h"
#include "inter.h"

void main ()
{
	FILE *plik=fopen("dane.txt", "r");

	int N;
	fscanf (plik, "%d", &N);
	printf ("%d\n", N);
	double *tabx;
	tabx=(double*)malloc(N*sizeof(double));
	double *taby;
	taby=(double*)malloc(N*sizeof(double));
	for (int i=0; i<N; i++)
	{
		fscanf(plik, "%lf", &tabx[i]);
		fscanf(plik, "%lf", &taby[i]);
		taby[i]=-taby[i];
		printf ("%lf\t %lf\n", tabx[i], taby[i]);
	}
	fclose (plik);

	graphics (1000,800);
	line (0,300,700,300);
	for (int i=0; i<N;i++)
	{
		setcolor(RED);
		circle (tabx[i], taby[i]+300, 4);
	}
	

	for (int i=0; i<600;i++)
	{
		double y=lagrange (tabx,taby,N,i);
		printf ("%lf\n", y);
		setcolor (0);
		circle (i, y+300, 3);
	}
	wait();
}

edytowany 1x, ostatnio: danielbr3
D3
  • Rejestracja:ponad 6 lat
  • Ostatnio:13 dni
  • Postów:58
0

Tutaj funkcja interpolujaca

Kopiuj
double lagrange( double *x, double *y, int n, double xx )
{
	int		i, j;
	double	yint, ylag;

	yint = 0.0;
	for ( i=0; i<n; i++ )
	{
		ylag = 1.0;
		for ( j=0; j<n; j++ )
		{
			if ( i == j)
				continue;

			ylag *= (xx - x[j]) / (x[i] - x[j]);
		}

		yint += y[i]*ylag;
	}

	return yint;
}

MarekR22
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:minuta
2

Ok teraz widzę w czym problem.
Wykraczasz poza zakres precyzji double.
Mając 128 punktów interpolując Lagrange'em dostajesz wielomian stopnia 127.
Teraz wyrazy przy dużych potęgach są dość duże i mają naprzemienne znaki. W efekcie jeśli jesteś daleko od środka, gdy wyższe potęgi mają większe znaczenie, to odejmujesz od siebie duże liczby, co jest obarczone dużym błędem, by potem dodawać do tego małe małe wartości.
Efekt jest taki, jak obserwujesz.
Matematycznie kod jest poprawny, ale ograniczenia precyzji double powoduje, że błędy obliczeń kumulują się za szybko.

Zastanawiam się czy da się to jakoś obejść? W sensie czy da się tak przekształcić ten algorytm by ograniczyć kumulowanie się błędów obliczeń.


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
MO
Można sklejać z kilku fragmentów ograniczając stopień wielomianu, użyć long double (choć tu może i to nie wystarczyć), lub użyć biblioteki do większej precyzji (np. GMP)

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.