Zufallszahl mit Gewichtung
-
Basierten auf meine Frage hab ich das gebastelt:
#include "FreeFunktion.h" //console::DontClose(); #include <iostream> #include <vector> using namespace std; int getRandomNumber(int Number, unsigned Sigma) { if(Sigma<2) return Number; double P = (double)rand() / RAND_MAX; double ItemCount = Sigma*Sigma; double ItemsForNextBound = 2; double nextBound = ItemsForNextBound/ItemCount; int Spread=1; while(P >= nextBound) { Spread++; ItemsForNextBound+=2*(Spread); nextBound = ItemsForNextBound/ItemCount; } if(rand()%2) return Number + (Sigma - Spread); return Number - (Sigma - Spread); } int main() { const unsigned Count=1E6; double sum=0; vector<double> Probs(21); cout<<"Test 1: \n"; for(unsigned i=0; i<Count; ++i) Probs[getRandomNumber(20, 4)-10]++; for(unsigned i=0; i<Probs.size(); ++i) { cout<<Probs[i]/Count<<"\n"; sum+=Probs[i]; } cout<<"Sum: "<<sum/Count; cout<<"Test 2: \n"; for(unsigned i=0; i<Count; ++i) Probs[getRandomNumber(20, 10)-10]++; for(unsigned i=0; i<Probs.size(); ++i) { cout<<Probs[i]/Count<<"\n"; sum+=Probs[i]; } cout<<"Sum: "<<sum/Count; console::DontClose(); //Verhindert bei mir das Schließen der Console }Bei betrachten des Tests 2 fällt auf das die "Mitte" des Arrays nur zu 10% getroffen wird, das ist zwar immernoch mehr als Jedes andere einzelne Element, aber zu 90% wird sie eben nicht getroffen. Ich möchte nun das die Mitte häufiger getroffen wird wie bei einer Gaußverteilung, möchte also die "Breite" der Gaußglocke bestimmen können, kann mir da Jemand helfen?
-
Meehhh, mir fällt grad auf das beim kopieren was schief gelaufen ist.
Hier die Richtige Version:#include "FreeFunktion.h" //console::DontClose(); #include <iostream> #include <vector> using namespace std; int getRandomNumber(int Number, unsigned Sigma) { if(Sigma<2) return Number; double P = (double)rand() / RAND_MAX; double ItemCount = Sigma*Sigma; double ItemsForNextBound = 2; double nextBound = ItemsForNextBound/ItemCount; int Spread=1; while(P >= nextBound) { Spread++; ItemsForNextBound+=2*(Spread); nextBound = ItemsForNextBound/ItemCount; } if(rand()%2) return Number + (Sigma - Spread); return Number - (Sigma - Spread); } int main() { const unsigned Count=1E6; double sum=0; vector<double> Probs(21); cout<<"Test 1: \n"; for(unsigned i=0; i<Count; ++i) Probs[getRandomNumber(20, 4)-10]++; for(unsigned i=0; i<Probs.size(); ++i) { cout<<Probs[i]/Count<<"\n"; sum+=Probs[i]; } cout<<"Sum: "<<sum/Count<< "\n"; sum=0; Probs.clear(); Probs.resize(21); cout<<"Test 2: \n"; for(unsigned i=0; i<Count; ++i) Probs[getRandomNumber(20, 10)-10]++; for(unsigned i=0; i<Probs.size(); ++i) { cout<<Probs[i]/Count<<"\n"; sum+=Probs[i]; } cout<<"Sum: "<<sum/Count; console::DontClose(); //Verhindert bei mir das Schließen der Console }
-
Die Breite einer Gaußverteilung legt man in der Regel durch sigma fest. Ich bin mir jetzt nicht ganz sicher, was getRandomNumber genau für eine Verteilung erzeugt. Wenn du normalverteilte Zufallszahlen (d.h. Gaußverteilung) erzeugen willst, könnte das hier interessant sein: http://de.wikipedia.org/wiki/Box-Muller-Methode.
Implementiert sieht das dann beispielsweise so aus:
double useful::rnd_boxMuller(double sigma) { double u1 = (rand()+1.) / (RAND_MAX+1.); double u2 = (rand()+1.) / (RAND_MAX+1.); double z1 = sqrt(-2*log(u1)) * cos(2*M_PI*u2); return z1*sigma; }Edit:
Ok, ich hab das Programm einmal ausgeführt. Erzeugt wird so eine dreiecksförmige Verteilung (linearer Anstieg der Wahrscheinlichkeit bis zum Erwartungswert). Willst du diese Form beibehalten? Wenn ja, bleibt dir eigentlich nur die Möglichkeit, ein kleineres Sigma zu wählen. Ansonsten könnte meine Funktion auch interessant sein (die Ausgabe hat den Erwartungswert 0).