Wyznaczanie środkowych wartości

0

Witam wszystkich. Chciałbym prosić o pomoc, ponieważ chciałbym wyliczyć wartość środkową, (interpolacja liniowa). skorzystałem ze wzoru x=(x-1) + (x+1) / 2. Program wczytuje dane z pliku i jeśli widzi że jakaś wartość jest pusta (na razie u mnie wartość pusta to "0" pózniej będę myślał jak zastąpić to pustą linijką :) ) to bierze dwie skrajne wartości i wylicza środkową. Zrobiłem program, który działa poprawnie tylko dla jednej pustej wartości w pliku, natomiast nie wiem jak zrobić aby program wyliczał wartości puste jeśli jest ich kilka z kolei.

 
12 13
2 2 
3 3
0 0
0 0
0 0
5 6
9 9
22 66
100 100

w tym miejscu programu jest liczona wartość środkowa , tylko dla jednej wartości, proszę o pomoc ponieważ stoję od kilku dni w miejscu i niewiem jak rozwiązać ten problem. Myślałem nad rekurencią, ale wole się zapytać tutaj.

 

for (int i=0; i<=10; i++){


    if ( (k[i](0,0) == 0) && (k[i](1,0) == 0) ){


    k[i]=(k[i-1]+k[i+1])/2;
{
     cout<<endl<<"Klatka "<<i<<": "<<endl<<k[i];
}

    }


    else {

        cout<<endl<<"Klatka "<<i<<": "<<endl;
        cout<<k[i];
    }

}

 


a tu cały program żeby było wiadomo o co chodzi:

 



#include <iostream>
#include <fstream>
#include <cstdlib>
#include <Eigen/Dense>

using namespace std;
using Eigen::Vector2d;


 Vector2d k[99];

 int x[100];
 int y[100];


int main()
{
    int liczba[10][2];
    ifstream plik("zrodlo.txt");

    for(int i = 0; i < 10; i++)
        for(int j = 0; j < 2; j++)
            plik >> liczba[i][j];


    for(int i = 0; i < 10; i++)
    {
        for(int j = 0; j < 2; j++)
       {
         x[i]=liczba[i][0];
         y[i]=liczba[i][1];

         cout << liczba[i][j] << " ";
        }
        cout << "\n";
    }


for ( int i=0;i<10; i++){
cout<<endl<<endl<<"x: "<<x[i];
cout<<endl<<endl<<"y: "<<y[i];
}


for ( int i=0; i<10; i++)
{
    k[i]<<x[i],y[i];
}

for (int i=0; i<=10; i++){


    if ( (k[i](0,0) == 0) && (k[i](1,0) == 0) ){


    k[i]=(k[i-1]+k[i+1])/2;
{
     cout<<endl<<"Klatka "<<i<<": "<<endl<<k[i];
}

    }


    else {

        cout<<endl<<"Klatka "<<i<<": "<<endl;
        cout<<k[i];
    }

}

    system("pause");


    return 0;
}


1

Co rozumiesz przez "wartość środkową"? Średnią? Medianę? Jeśli średnią, to liczysz tylko z dwóch elementów, a nie ze zbioru. Jeśli medianę, to musisz sortować i dopiero brać to, co jest w połowie tablicy, ew. wyliczać średnią dwóch środkowych wartości.

Poza tym:

  1. Styl.
  2. Po co Ci ten Vector2d? Naprawdę nie da się tego zrobić tablicą dwuelementową?

Edit:
3. Jeśli to interpolacja, to użycie wszędzie typów int skutecznie wspomaga nas w gubieniu ważnych danych i wyliczaniu bzdur, czyż nie?

0

Wiem że Vector2d jest niepotrzebny, i można to zrobić inaczej. Uczę się operacji na wektorach i macierzach i chciałem sprawdzić jak są one czytane przez program. Wartość środkową rozumiem w taki sposób: jeśli program czyta klatki a w każdej klatce znajduje się x oraz y , to program powinien policzyć wartość gdy w jakiejś klatce zabraknie x oraz y. Program liczy mi wartość dla jednej klatki, a ja chciałbym aby liczył wartości dla kilku klatek(bez wartości) po kolei.
np :

klatka1: x=1  y=1
klatka2: x=2  y=2
klatka3: x=3  y=3
klatka4: x=  y=
klatka5: x=  y=
klatka6: x=  y=
klatka7: x=7 y=8
...     ....
...     ....
 

a więc chcę aby program wyliczył wartości dla klatek 4,5,6. U mnie wartości puste są zapisane jako "0" ponieważ nie wiem na razie jak zrobić aby czytało mi: " " jako x oraz y, ale nie o to prosze, poradze sobie z tym pózniej.

Wiem że aby policzyć dane z przykładu który podałem muszę wyliczyć najpierw za pomocą klatki 3 oraz klatki 7, klatke 5 , aby za jej pomocą policzyć klatkę 4 oraz klatkę 6.Ale to tylko prosty przykłąd, a co w przypadku większej ilości pustych klatek ...? Dlatego proszę o pomoc , ponieważ nie wiem jak to zrobić.

0

O widzisz, to teraz rozumiemy, o co chodzi. Próbujesz za pomocą interpolacji uzyskać wartości w brakujących punktach. Moim zdaniem, to, co powinieneś policzyć to tzw. wielomian interpolujący i na jego bazie wyciągać brakujące wartości. Zwróć też uwagę, że brakujące wartości mogą niekoniecznie znajdować się dokładnie w środku przedziałów (masz na to jakieś gwarancje?). Poniżej wklejam kod do liczenia interpolacji Lagrange'a - korzystaj do woli.

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int
main(int argc, char ** argv)
{
	double *x, *y;
	int t, n, k, i, j, n_a;

	scanf("%d", &t);
	for (; t > 0; t--) {
		scanf("%d", &n);

		assert(n > 0);
		x = calloc(n, sizeof(double));
		y = calloc(n, sizeof(double));
		assert(x != NULL);
		assert(y != NULL);

		for (i = 0; i < n; i++)
			scanf("%lf %lf", x+i, y+i);

		scanf("%d", &n_a);
		assert(n_a > 0);
		/* W zmiennej ask mamy współrzędną x punktu, o który pytamy. */
		for (k = 0; k < n_a; k++) {
			double res;
			double ask;

			res = 0;
			scanf("%lf", &ask);
			for (i = 0; i < n; i++) {
				double tmp;

				tmp = y[i];
				/* Wyliczamy wartość wielomianu w punkcie (ask). */
				for (j = 0; j < n; j++) {
					if (j != i)
						tmp *= (ask - x[j]) / (x[i] - x[j]);
				}
				res += tmp;
			}
			/* Wyświetlamy f(ask). */
			printf("%.3lg\n", res);
		}

		free(x);
		free(y);
	}

	return (0);
}

Edit: +komentarz, +asercje po calloc

0

dziękuję, tylko chodziło mi o zwykłą interpolację liniową :). Czyli co w moim kodzie zrobić, aby program liczył mi brakujące wartości. Może jakiś wzór rekurencyjny? Chodzi o to że nie, próbowałem już różne kombinacje ale zawsze wywala mi niepoprawne wartości (dla przykładowych 1,2,3,4 żeby było łatwiej).

0

Jak byś robił interpolację liniową, to miałbyś tylko dwa punkty i wtedy zadanie wyglądałoby tak:

x1 y1
x2 y2
// policz f((x1 + x2) / 2) i kolejny zestaw...

Ty masz więcej punktów, a to raczej implikuje wielomianową.

No chyba, że bawimy się w interpolację łamaną, ale wtedy zaczyna mi to przypominać aproksymację wielomianową stopnia pierwszego stosowaną np. w metodzie elementów skończonych. Wtedy to może iść rekurencyjnie, a nawet potrafi mieć adaptację kroku - gdyby punkty nie były rozmieszczone równomiernie.

0

Chyba zrozumiałem do końca o co Ci chodziło.

Chcesz podać do programu znane wartości funkcji w zadanych punktach (w interpolacji: węzły interpolacyjne). Chcesz też podać punkty, w których oczekiwałbyś, że program poda Ci wartości funkcji. I teraz masz dwie opcje:

  1. Interpolacja wielomianowa, która znając tylko znane punkty funkcji poda Ci interpolowane wartości funkcji w punktach, w których nie znamy wartości funkcji explicite.
  2. Aproksymacja, w której przybliżamy funkcję inną funkcją, ale w takim przypadku musimy wiedzieć "coś więcej" o funkcji. Np. wiesz, że Twoja funkcja jest np. parabolą albo wielomianem trzeciego stopnia. W szczególności dla MRS i MES musisz znać równanie różniczkowe, czyli wiedzieć coś o pochodnych tej funkcji + warunki na końcach przedziału (von Neumanna, Cauchyego, Dirichleta, Robina, ew. wariacje powyższych). Tej wiedzy nie posiadasz, a akurat MES z bazą wielomianową stopnia 1 potrafiłby Ci skonstruować dokładnie taką łamaną, jaką jak mniemam oczekujesz. Ale u Ciebie nie podałeś w żaden sposób informacji o pochodnych.

Moim zdaniem jedyne, co możesz zrobić w przypadku, który podałeś to jest dokładnie interpolacja wielomianowa, do której kod podałem Ci wyżej. Niczego innego nie osiągniesz, bo albo robisz po prostu odcinek między kolejnymi znanymi punktami i wtedy masz wszystkie nieznane punkty na jednym odcinku (np. jak w Twoim pierwszym przypadku) albo po prostu wróżysz z fusów i wtedy każdy wynik jest jednakowo dobry (lub zły).

0

Chodzi mi o interpolację liniową. Mam znane wartości które wczytuje z pliku , linijka po linijce. I jeśli w pliku usunę kilka linijek to muszę za pomocą interpolacji liniowej podać ich wartości. (wartości nie muszą być takie jak były wczsniej ) Interpolacja ma mi z znanych wartości policzyć te nieznane, a jeśli się będą różnic to nic, o to chodzi. czyli jeszcze raz na spokojnie:

mam plik tekstowy a w nim :

1 1
2 2
3 3
4 4



8 8
9 9 
10 10

 

Program czyta pierwszą kolumnę jako x drugą jako y , tak mi to wczytuje do programu. wiersz 5 , 6 ,7 ma mi policzyc za pomocą interpolacji liniowej. Podałęm funkcje liniową, wiadomo ze policzy wartości takie jak powinny być. to przykład w bardziej zagmatwanej funkcji wiadomo ze intrpolacja podała by wartości całkiem inne niż funkcja powinna przyjąć, ale o to chodz mi właśnie. Program ma ro robić za pomocą wzoru : x=(x-1)+(x+1)/2 . I tak mi robi właśnie, ale niestety dla jednej brakującej wartości, a ja proszę tylko o to jaki wzór mam dać w moim kodzie aby liczył to dla kilku brakujących wartości jak w powyższym przykładzie(nie ma 3 wierszy).

0

No to bierzesz pierwszy i ostatni wiersz i na jego podstawie liczysz wszystkie pozostałe. Nie do końca widzę w czym problem.
Inne pytanie, masz taki zestaw:

-3 9
-2 4
-1 1
0 0
1 1
2 4
3 9

Usuwasz z niego (-1, 1), (0, 0) oraz (1, 1). Zadajesz pytanie tylko o (0, 0). Jaka powinna być Twoim zdaniem prawidłowa wartość? (0, 4) jak wynika z częściowej interpolacji łamaną bez 3 środkowych punktów czy (0, 0)?

0

Właśnie :) biorę pierwszy i ostatni wiersz :) , dzięki temu otrzymuje środkowy brakujący, dzieki któremu wyliczę pozostałe :).

przykład:

wiersz1: 12 15
wiersz2: 26 8
wiersz3:
wiersz4:
wiersz5:
wiersz6:
wiersz7:
wiersz8: 17 12
wiersz9 28 27

więc program bierze mi wiersz2 oraz wiersz8 i wylicza mi wiersz5 . Tak to ma wyglądać. x=26+17/2 i y=8+12/2 ; x=12.5 y = 10 . Właśnie o to chodzi :). A potem dzięki wartości wiersz5 chce wyliczyć inne brakujące: wiersz3, wiersz4, wiersz6 i wiersz7. Tylko że jestem początkowym programistą i od samego początku próbuję zapytać jak to zrobić ???? za pomocą rekurencji jakiejś???

Umiem tylko zrobić taki program (liczy tylko jedną brakującą wartość ponieważ nie wiem co zrobić w przypadku takim jak powyżej gdy brakujących wartosci jest więcej ):

podawałem go powyżej ale ten kod wysle jeszcze raz bo wiem ze to tu trzeba cos zrobić


for (int i=0; i<=10; i++){

if (x[i] == 0)
{
x[i]=(x[i-1]+x[i+1])/2;
cout<<endl<<"Klatka "<<i<<": "<<endl<<x[i]<<endl;
}

else {

        cout<<endl<<"Klatkaa "<<i<<": "<<endl<<x[i]<<endl;
     }
}
 
0

Możesz też odnaleźć sąsiadujące punkty, które nie są (0, 0). Tzn. poprzedzający (0, 0) i taki, który jest zaraz za nim. Do tego nie trzeba rekurencji.

Tak swoją drogą - to dziwne zadanie robisz. Nie odbieraj tego jako krytykę siebie, ale zajmuję się m.in. profesjonalną numeryką i akcja pt. "zrobię sobie prosty odcinek zamiast wycinka paraboli" powoduje, że włos mi się jeży na głowie. Załóżmy, że coś takiego odstawia inżynier Boeinga konstruujący nowy samolot. Zastępuje sobie po cichu w programie kawałek siatki nowego samolotu takim "wypłaszczeniem", po czym wysyła tak zmodyfikowaną siatkę dalej, np. do jakiegoś innego inżyniera, który będzie na niej robił symulację przepływu powietrza. Teraz zagadka: jak szybko koleś wyleci z roboty i z jak dużym hukiem?

0

Prosty odcinek podałem dla zrozumienia i łatwiejszego wytłumaczenia mojego problemu, równie dobrze mogą to być trudniejsze funkcje, mi tylko chodzi żeby ktoś na prostym przykładzie pomógł mi w wyznaczeniu brakujących wartości, które będą oczywiście błędne jesli nie będzie to funkcja liniowa, ale po prostu BĘDĄ , bo potem muszę zrobić analize, jak bardzo punkty z intrpolacji liniowej różnią się od punktów które były wczesniej. A że c++ ucze się od niedawna to nie wiem jak wyznaczyć te wartości, jak powinien wyglądać mój kod, dlatego tutaj zamieszczam swój post.

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