Streungsmaße
-
hallo zusammen . ich habe ein programm erstellt indem ich Streuungsmaße berechnen will, da wir grade in mathe das thema haben und ich somit am pc schneller rechnen kann
leider hab ich ab der Berechnung der Absoluten Abweichung einen Fehler, sodass mir total falsche werte ausgegeben werden könntet ihr vllt einmal drüber gucken?
wäre super nett
//Streuungsmaße.cpp: Hauptprojektdatei.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include<iomanip>
using namespace System;
using namespace std;//Get und Set Methoden in Klassen
class Stichprobe {
private:
int m_Max;
int m_Min;
int m_Spannweite;
double m_Varianz;
double m_Varianz2;
double m_AbsoluteAbweichung;
double m_AbsoluteAbweichung2;
double m_StandardAbweichung;
double m_Arithmetisch;
double m_Arithmetisch2;
int m_Stich;public:
void setMax(int Max){m_Max = Max;};
void setMin(int Min){m_Min = Min;};
void setStich(int Stich){m_Stich = Stich;};
void setArithmetisch(double Arithmetisch){m_Arithmetisch = Arithmetisch;};
void setArithmetisch2(double Arithmetisch2){m_Arithmetisch2 = Arithmetisch2;};
void setSpannweite(int Spannweite){m_Spannweite = Spannweite;};
void setVarianz(double Varianz){m_Varianz = Varianz;};
void setVarianz2(double Varianz2){m_Varianz2 = Varianz2;};
void setAbsoluteAbweichung(double AbsoluteAbweichung){m_AbsoluteAbweichung = AbsoluteAbweichung;};
void setAbsoluteAbweichung2(double AbsoluteAbweichung2){m_AbsoluteAbweichung2 = AbsoluteAbweichung2;};
void setStandardAbweichung(double StandardAbweichung){m_StandardAbweichung = StandardAbweichung;};
int getMin(){return m_Min;};
int getMax(){return m_Max;};
int getStich(){return m_Stich;};
double getArithmetisch(){return m_Arithmetisch;};
double getArithmetisch2(){return m_Arithmetisch2;};
int getSpannweite(){return m_Spannweite;};
double getVarianz(){return m_Varianz;};
double getVarianz2(){return m_Varianz2;};
double getAbsoluteAbweichung(){return m_AbsoluteAbweichung;};
double getAbsoluteAbweichung2(){return m_AbsoluteAbweichung2;};
double getStandardAbweichung(){return m_StandardAbweichung;};
void calcArithmetisch();
void calcSpannweite();
void calcVarianz();
void calcAbsoluteAbweichung();
void calcStandardAbweichung();
};void Stichprobe::calcSpannweite()
{
m_Spannweite = m_Max - m_Min;
}
void Stichprobe::calcArithmetisch()
{
m_Arithmetisch = m_Arithmetisch2 / m_Stich;
}
void Stichprobe::calcAbsoluteAbweichung()
{
m_AbsoluteAbweichung = m_AbsoluteAbweichung2 / m_Stich;
}
void Stichprobe::calcVarianz()
{
m_Varianz = m_Varianz2 / m_Stich;
}
void Stichprobe::calcStandardAbweichung()
{
m_StandardAbweichung = sqrt(m_Varianz);
}int main()
{
Stichprobe Rechnung;
Rechnung.setMax(-100000000);
Rechnung.setMin(100000000);
Rechnung.setArithmetisch2(0);
double stich=1;
double Stichprobe[100];cout << "Wie viele Werte moechten Sie eingeben?" << endl;
cin >> stich;
if (stich<=0)
{
cout << "Bitte geben Sie eine Zahl ein, die groesser als 0 ist!" << endl;
system("PAUSE");
return 0;
}
cout << "Sie moechten " << stich << " Werte eingeben!" << endl << endl;Rechnung.setStich(stich);
for(int i=0;i<stich;i++)
{
cout << "Bitte geben Sie den " <<i+1<< "ten Wert ein!" << endl;
cin >> Stichprobe[i];
cout << endl;
}//Berechnung der Spannweite
for(int i=0;i<stich;i++)
{
if(Stichprobe[i]>Rechnung.getMax())
{
Rechnung.setMax(Stichprobe[i]);
}
}
for(int i=0;i<stich;i++)
{
if(Stichprobe[i]<Rechnung.getMin())
{
Rechnung.setMin(Stichprobe[i]);
}
}Rechnung.calcSpannweite();
//Berechnung des rithmetischem Mittels
for(int i=0;i<stich;i++)
{
Rechnung.setArithmetisch2(Stichprobe[i]+Rechnung.getArithmetisch2());
}Rechnung.calcArithmetisch();
//Berechnung Absolute Abweichung
for(int i=0;i<stich;i++)
{
Rechnung.setAbsoluteAbweichung2(fabs((Stichprobe[i]-Rechnung.getArithmetisch()))+Rechnung.getAbsoluteAbweichung2());
}
Rechnung.calcAbsoluteAbweichung();//Berechnung Varianz
for(int i=0;i<stich;i++)
{
Rechnung.setVarianz2(((Stichprobe[i]-Rechnung.getArithmetisch())*(Stichprobe[i]-Rechnung.getArithmetisch()))+Rechnung.getVarianz2());
}Rechnung.calcVarianz();
//Berechung der Standardabweichung
Rechnung.calcStandardAbweichung();cout << endl << "Arithmetisches Mittel: " << Rechnung.getArithmetisch();
cout << endl << "Spannweite: " << Rechnung.getSpannweite();
cout << endl << "mittlere absolute Abweichung: " << Rechnung.getAbsoluteAbweichung();
cout << endl << "Varianz: " << Rechnung.getVarianz()<< setprecision(2);
cout << endl << "Standardabweichung: " << Rechnung.getStandardAbweichung()<< endl << endl;system("PAUSE");
return 0;
}
-
1. cpp-Tags benutzen
2. Wo genau ist der Fehler?
2.1. In welcher Zeile weicht das tatsächliche Ergebnis von dem gewünschten ab?
2.2. Gibt es Fehlermeldungen?
-
Wir spielen nicht für dich den Debugger. Stepp' durch und sieh' dir die Werte deiner Variablen an, lass dir Zwischenergebnisse ausgeben um den Fehler einzugrenzen.
greetz, Swordfish
-
wenn du dann noch zeit und lust hast, dann google mal nach "const-correctness" (und klick dann auf den link wo steht "meinten sie..." , weil das sicherlich anders geschrieben wird - egal ^^)
die cpp-tags wurden zum glück schon angemeckert - lässt sich wirklich n1 lesen so... xD fällt dir das nicht selbst auf? OO
//edits:
einrücken sollte dann auch noch drin sein ^^
Rechnung.setVarianz2(((Stichprobe[i]-Rechnung.getArithmetisch())*(Stichprobe[i]-Rechnung.getArithmetisch()))+Rechnung.getVarianz2());
auf so ne konstrukte würd ich verzichten - entwieder du machst aus der variable nen public-member oder du baust dir noch ne fkt 'AddVarianz' oder so... aber so, wie es jz ist, find ich nicht nur sehr unübersichtlich sondern das halt ich auch für ineffektiv...
Vll solltest du dir auch überlegen, Varianz etc in der Klasse an sich berechnen zu lassen (dafür ist so ne Klasse ja da - das die Fkt, die dazugehören und die Daten benötigen darin zusammengefasst werden können ^^ können - nicht müssen - aber ich seh kein nachteil darin ^^)dann für die setter-methoden von double oder float werden:
setxyz (const float &var) /*eine konstante referenz übergeben (so was ähnliches, wie nen pointer... constant, weil du var hier nicht veränderst - wenn du nur 'float var' schreibst, dann kopiert er die werte jedes mal hin und her... */ { m_var = var; };
an deiner stelle würd ich vll auch noch ne einfache fkt zum quadrieren schreiben, wenn du pow nicht verwenden willst ^^
Stichprobe Rechnung; /* Stichwort "Konstruktor" (auch Ctor genannt)... Da kannste deine Werte alle direkt richtig initialisieren lassen... */ Rechnung.setMax(-100000000); Rechnung.setMin(100000000); Rechnung.setArithmetisch2(0); double stich=1; //was spricht hier gegen einen int? double Stichprobe[100]; //nimm vll wenigstens 'Stichwert' oder irgend so nen Wert - nicht unbedingt den Name der Klasse ^^ //Ctor: class Tmysimpleclass { private: float m_var; public: Tmysimpleclass (void) {}; /*vorhanden ist der Standard-Ctor so und so immer - sonst wird er vom Compiler erzeugt - so eben von dir... genau so gut kann man da auch gleich noch was sinnvolles mit anstellen: */ Tmysimpleclass (const float &_var) {m_var = _var}; //so was macht man allerdings eher mit ner Initialisierungsliste: Tmysimpleclass (const float &_var) : m_var (_var) {/*nothing to do?!*/}; //destruktor: ~Tmysimpleclass (void) { //nichts machen - du hast ja keine pointer die, zu löschen wären angelegt - deshalb kann man den (wie immer ^^) weglassen... }; };
versuch mal, nen bissl was davon einzubauen - damit das bissl übersichtlicher wird und dann post einfach noch mal ^^
//noch nen edit:
So weit hab ich deine Klasse mal verunstaltet - sicherlich gibt es auch viele andere Möglichkeiten, aber ich hab die gewählt (ist noch nicht alles dabei, weil ich zwar lange Weile hab aber au langsam müde werd ^^)#include <iostream> #include <string> #include <vector> using namespace std; //Get und Set Methoden in Klassen struct Wertebereich { private: double max, min; double spannweite; public: Wertebereich (const double &a = 99999999, const double &b = -99999999) : min (a), max (b) {}; //alternativ könnte man WB auch mit dem ersten Wert initialisieren - wäre aber auch noch in der rechnung-klasse bissl arbeit... // Wertebereich (const double &firstvalue) : min (firstvalue), max (firstvalue) {}; void NewValue (const double &a) { if (a < min) min = a; else if (a > max) max = a; }; double GetMax (void) const {return max;}; double GetMin (void) const {return min;}; double GetSpannweite (void) const {return spannweite;}; void calcSpannweite (void) { spannweite = max - min; }; }; class Stichprobe { private: Wertebereich WB; vector <double> eingaben; double summe, arithmetisches_mittel; public: //Getter int GetMin (void) const {return WB.GetMin ();}; int GetMax (void) const {return WB.GetMax ();}; size_t GetAnz (void) const {return eingaben.capacity ();}; double GetSpannweite (void) const {return WB.GetSW;}; double getArithmetischesMittel (void) const {return arithmetisches_mittel;}; public: //Setter void SetAnz (void) //hier würde ich die komplette eingabe regeln... { //Eingabe so lange der User verstanden hat, was hinter der Vorderung eine Zahl größer als 0 einzugeben ^^ cout << "Wie viele Werte moechten Sie eingeben?" << endl; int anz; cin >> anz; //das ganze könnte man auch noch mit fail (); überprüfen cin.fail (); oder so - aber egal hier ^^ while (anz < 1) { while (!cin.eof ()) //muell wegtun (weil bei ner eingabe von 'a' bleibt a ja drin, wenn ich nen double raushaben will... { string dumb; cin >> dumb; }; cout << "Bitte geben Sie eine Zahl ein, die groesser als 0 ist!" << endl; cin >> anz; }; cout << "Sie moechten " << anz << " Werte eingeben!\r\n" << endl; for(size_t i (0); i < anz; ++i) //preincrement ist dem postincrement eigtl vorzuziehen - macht hier keinen unterschied, weil das compiler wegoptimiert, erst bei pointern... aber ich finde, man kann es sich ruhig angewöhnen... { cout << "Bitte geben Sie den " <<i+1<< "ten Wert ein!" << endl; double in (WB.GetMin () -1); cin >> in; //TODO: richtig machen... siehe erste eingabe etc ^^ while (in < WB.GetMin ()) { cout << "nochmal...:"; cin >> in; cout << endl; }; summe += in; eingaben.push_back (in); cout << endl; } }; public: //'richtige' fkt + ctor etc Stichprobe (void) : anz (0), summe (0), WB (), arithmetisches_mittel (0) {}; void calcSpannweite (void) { WB.calcSpannweite (); } void calcArithmetischesMittel (void) { arithmetisches_mittel = summe / anz; } void calcirgendwaswomanalleelementedurchguckenmuss (void) { const vector <double>::const_iterator ende (eingaben.end ()); double mysquaresum (0); for (vector <double>::const_iterator it (eingaben.begin ()); it != end; ++it) { *it; //so sprichst du den wert an... mysquaresum += (*it)*(*it); } } };
Ich hoffe, es gefällt dir und du weist was damit anzustellen ^^ Jz hab ich genug edits gebraucht - jz bist du dran ;o)
Bye
-
Rieper schrieb:
... leider hab ich ab der Berechnung der Absoluten Abweichung einen Fehler, sodass mir total falsche werte ausgegeben werden könntet ihr vllt einmal drüber gucken?
Du hast so viele (un)schöne Methoden, aber eine der wichtigsten hast Du vergessen - nämlich den Konstruktor
Stichprobe() : m_Max(-100000000), m_Min(100000000), m_Spannweite(0), m_Varianz(0), m_Varianz2(0), m_AbsoluteAbweichung(0), m_AbsoluteAbweichung2(0), m_Arithmetisch(0), m_Arithmetisch2(0) {}
fügt man ihn hinzu, sieht das Ergebnis schon besser aus.
Die Art und Weise wie Du die Klasse benutzt ist übrigens gänzlich kontraproduktiv - hast Du Interesse mehr darüber zu erfahren?
Gruß
Werner
-
unskilled schrieb:
setxyz (const float &var) /*eine konstante referenz übergeben (so was ähnliches, wie nen pointer... constant, weil du var hier nicht veränderst - wenn du nur 'float var' schreibst, dann kopiert er die werte jedes mal hin und her... */ { m_var = var; };
Man sollte zwar konstante Referenzen bei Objekten verwenden, aber im Falle von den C++ Basisdatentypen (wie int, long, float, double) ist eine Kopie in der Regel sinnvoller (und kann je nach Compiler auch schneller sein).
Grobe Richtschnur für Parameter:
1. Ist NULL zulässig? [Ja] Pointer nötig [Nein] Wertübergabe oder Referenz vorziehen 2. [Nur bei Zeiger] Soll die Adresse änderbar sein? [Ja] Referenz auf Zeiger *& oder Doppelpointer ** [Nein] Zeiger const machen (Foo * const value) 3. Soll der Wert änderbar sein? [Ja] Referenz/Zeiger nötig [Nein] Wert const machen (Bei Wertübergabe nur optional, Bei Referenz/Zeiger würde ich es tun) 4. Ist der Wert ein Objekt, oder ein Basisdatentyp (wie int) [Objekt] Referenz/Zeiger [Basisdatentyp] Wertübergabe, sofern nichts anderes dagegen spricht
cu André
-
also:
1. bei float oder zumindest bei double sollte referenz schneller sein - und selbst, wenn nicht - der compiler macht das scho ^^ also zur not schreib immer const & vartype varname - compiler nimmt scho das, was am schnellsten istbyebye