Mittelwert bilden und vergleichen
-
Hallo leute,
ich weiß nicht ob mein thema hierher gehört, aber s hat ja was mit mathe zu tun.habe ein array vom typ double mit werten 160.234;160.345 usw.
die anzahl der werte richtet sich bei mir nach der auflösung z.b.128,256,512. so dass ich dann auch so viele werte bekomme.
jetzt möchte ich einen mittelwert bilden, jedoch so, dass ich den ersten wert nehme und mit dem 2-wert vergleiche.
wenn die abweichung kleiner als ca.2-3 ist, dann soll der mittelwert gebildet werden.
der mittelwert(letzter mittelwert+nächter wert) soll solange gebildet werden, bis ein vergleich mir gibt, dass die abweichung vom letzten mittelwert zum nächsten wert größer als 2-3 ist.
der haken ist noch, dass ich nach dem vergleich(wenn der wert größer als 2-3 ist) noch weitere 5werte mit dem mittelwert vergleichen will.
wenn diese auch eine abweichung haben, dann soll mir der letzte mittelwert(vor dem 1."fehlervergleich" erhalten bleiben)und anschließend rausgesprungen werden.
ich weiß wie ich das in mathe machen soll, aber wie bringe ich dies in C++ unter??
-
Dieser Thread wurde von Moderator/in Jester aus dem Forum Mathematik in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Und jetzt nochmal langsam zum Mitschreiben.
Normalerweise bildet man den Mittelwert einer Zahlenreihe, indem man alle ankommenden Zahlen aufaddiert und die Summe durch die Anzahl teilt. Was du da wie und womit vergleichen willst, ist mir (ehrlich geagt) schleierhaft.
-
Hab verstanden, was du meinst und wie du das machen willst
PiotreD schrieb:
ich weiß wie ich das in mathe machen soll, aber wie bringe ich dies in C++ unter??
Du könntest eine Art Algorithmus dafür entwickeln. Also das ganze auf einem Blatt Papier machen und überall, wo du dich entscheiden musst, schreibst du das auch hin.
Du musst es also so aufschreiben, dass auch jemand, der nur das geschriebene sieht, das auch selber machen könnte. Dann ver-mathematisierst du das ganze, indem du statt
"wenn die abweichung kleiner als ca.2-3 ist, dann soll der mittelwert gebildet werden"
dann sowas hier schreibst:
"abweichung = LetzterMittelwert - AktuelleZahl
wenn abweichung kleiner 2
dann mache dies
sonst mache das" uswIrgendwann ist es dann eine Art Algorithmus, den du mehr als einfach in Quellcode umsetzen kannst
Und sowas wie "ca" kommt in einem Algorithmus nicht vor, der muss schon schrittweise und präzise sein :p
-
Es gäbe die Möglichkeit zunächst den Mittelwert zu bilden, dann den Wert zu suchen, der am weitesten vom Mittelwert entfernt liegt und diesen dann zu entfernen, wenn der Abstand zum Mittelwert größer als eine vorgegebene Toleranz ist. Das wiederholt man solange bis der am weitesten entfernte Wert innerhalb der Toleranz liegt.
In C++:#include <algorithm> // max_element #include <iostream> #include <cstdlib> // std::abs( double ) #include <cmath> // std::abs( double ) bei VC8 #include <list> #include <numeric> // accumulate struct AbstandZu { explicit AbstandZu( double ref ) : m_ref( ref ) {} // 'true', falls a näher an m_ref liegt als b bool operator()( double a, double b ) const { return std::abs( a - m_ref ) < std::abs( b - m_ref ); } private: double m_ref; }; template< typename InItr > double mittelwert( InItr von, InItr bis, double tol ) { using namespace std; list< double > werte( von, bis ); double mittelwert = accumulate( werte.begin(), werte.end(), 0.0 ) / werte.size(); for( list< double >::iterator i ; i = max_element( werte.begin(), werte.end(), AbstandZu( mittelwert ) ), std::abs( *i - mittelwert ) > tol; ) { mittelwert = (mittelwert * werte.size() - *i) / (werte.size() - 1); // neuen Mittelwert ohne *i // cout << "Loesche " << *i << endl; werte.erase( i ); } return mittelwert; } int main() { using namespace std; const double arr[] = { 3.1, 9.6, 3.3, -90.7, 3.3, 3.1 }; cout << "Mittelwert: " << mittelwert( arr, arr + sizeof(arr)/sizeof(*arr), 2.0 ) << endl; return 0; }
Gruß
Werner
-
hi..also, ich habe versucht deinen code zu verstehen, nur leider bin ich nicht so gut. könntest du mir nochmal erklären, was die einzelnen abschnitte so machen.
habe wohl verstanden, dass mir das programm sozusagen nur die werte nimmt, die innerhalb der toleranz von 2.0 liegen.
ist das jetzt so: ich bilde einen mittelwert über wieviele werte? anschließend vergleiche ich den mittelwert mit dem nächste wert. falls dieser >2 ist, dann wird er nicht berücksichtigt und gelöscht.
kann ich mir auch ausgeben lassen, wo sozusagen die grenze ist, d.h wann der mittelwert nicht mehr mit dem nächsten wert übereinstimmt?
müßte ja in eine variable einbringen. sozusagen dass ich 2werte bekomme:einmal von links und einmal von rechts. geht dies?
-
PiotreD schrieb:
hi..also, ich habe versucht deinen code zu verstehen, nur leider bin ich nicht so gut. könntest du mir nochmal erklären, was die einzelnen abschnitte so machen.
Also noch mal im einzelnen:
int main() { using namespace std; const double arr[] = { 3.1, 9.6, 3.3, -90.7, 3.3, 3.1 }; cout << "Mittelwert: " << mittelwert( arr, arr + sizeof(arr)/sizeof(*arr), 2.0 ) << endl; return 0; }
da ist ein Array 'arr' mit doubles. An die Funktion 'mittelwert' wird der Zeiger auf das erste (arr) und letze (arr + sizeof(arr)/sizeof(*arr)) und eine Toleranz von 2.0 übergeben.
Anschließend wird das, was die Funktion mittelwert zurückliefert, ausgegeben.template< typename InItr > double mittelwert( InItr von, InItr bis, double tol ) {
das ist Template, d.h man kann hier einen beliebigen Typen einsetzen, der (in diesem Fall) alle Anforderungen nach einem Input-Iterator erfüllt. In diesem konkreten Fall könnte man auch 'const double*' statt InItr schreiben und die Zeile mit 'template' weglassen.
using namespace std; list< double > werte( von, bis );
hier werden jetzt zuerst alle Werte in eine Liste mit Namen 'werte' kopiert. Ich benutzte deshalb eine Liste, da ich dann sehr effizient Elemente, die mitten drin stehen, daraus wieder löschen kann.
double mittelwert = accumulate( werte.begin(), werte.end(), 0.0 ) / werte.size();
mit dem Algorithmus 'accumulate' werden alle Werte der Liste zusammengezählt und anschließend wird das Ergebnis durch die Anzahl der Elemente (werte.size()) geteilt. Damit erhält man den Mittelwert aus allen (!) Werte.
for( list< double >::iterator i ; i = max_element( werte.begin(), werte.end(), AbstandZu( mittelwert ) ), std::abs( *i - mittelwert ) > tol; ) {
Hier wird jetzt mit dem Algorithmus max_element, dasjenige Element gesucht, das am weitesten vom Mittelwert entfernt ist. Als Ergebnis bekommt man einen Iterator 'i', der auf eben dieses Element zeigt. Gleich anschließend wird geschaut, ob der absolute Abstand zum Mittelwert größer als 'tol' ist. Falls nein, wird die for-Schleife abgebrochen.
Falls ja ...
mittelwert = (mittelwert * werte.size() - *i) / (werte.size() - 1); // neuen Mittelwert ohne *i // cout << "Loesche " << *i << endl; werte.erase( i ); } return mittelwert; }
... wird ein neuer Mittelwert ohne dieses am weitesten entfernte Element '*i' berechnet und das Element aus der Liste entfernt.
Danach wird durch die for-Schleife wieder das am weitest entfernte Element aus den noch verbliebenen Elementen gesucht - usw. (s.o.)Bei Abbruch der Schleife wird der aktuelle Mittelwert zurückgegeben.
Wenn man das 'cout << ' auskommentiert erhält man als Ausgabe:
Loesche -90.7 Loesche 9.6 Mittelwert: 3.2
PiotreD schrieb:
habe wohl verstanden, dass mir das programm sozusagen nur die werte nimmt, die innerhalb der toleranz von 2.0 liegen.
korrekt
PiotreD schrieb:
ist das jetzt so: ich bilde einen mittelwert über wieviele werte?
beim ersten Mal über alle
PiotreD schrieb:
anschließend vergleiche ich den mittelwert mit dem nächste wert. falls dieser >2 ist, dann wird er nicht berücksichtigt und gelöscht.
nein nicht mit dem nächsten Wert, sondern es wird der Wert von allen noch verbliebenen gesucht, der am weitesten vom Mittelwert entfernt ist. Und dieser wird dann gelöscht, falls der Abstand größer 'tol' (hier ==2.0) ist.
PiotreD schrieb:
kann ich mir auch ausgeben lassen, wo sozusagen die grenze ist, d.h wann der mittelwert nicht mehr mit dem nächsten wert übereinstimmt?
müßte ja in eine variable einbringen. sozusagen dass ich 2werte bekomme:einmal von links und einmal von rechts. geht dies?
Hier versteh ich die Frage nicht. Kannst Du mal ein Zahlenbeispiel bringen, und an Hand dieses Zahlenbeispiels nochmal fragen.
Gruß
Werner