PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : zufällige Dauer mit Gaußscher Normalverteilung



M1.R
20.06.2007, 10:49
Liebe Theoretiker!

Mein ASURO soll eine zufällige Zeit zwischen 0 und ca. 1 sec warten:
Msleep(Zufallszahl).
Nun habe ich Zufallszahlen zwischen 0 und 1020, die alle mit gleicher Wahrscheinlichkeit auftreten.
Der ASURO soll aber meistens ca. 1/2 sec warten, manchmal länger, manchmal kürzer.
Die Wahrscheinlichkeit meiner Zufallszahlen sollte also wie bei einer Gaußschen Normalverteilung sein. (die mittleren Zahlen müssten öfter vorkommen, die niedrigen und die hohen seltener)

Hat jemand eine Idee, wie man das machen könnte?

Gruss
M.

damaltor
20.06.2007, 10:55
nim die summe von 10 zufallszahlen. die mittleren werte der summe (ca 5000) werden sich häufen, da gleichmässig viele hohe und niedrige werte kommen und sich so ausgleichen. die chance, dass viele niedrige werte kommen, (kurze wartezeit) oder dass viele hohe werte kommen (lange wartezeit) ist geringer, als dass sowohl hohe als auch niedrige werte kommen (mittlere wartezeit).

je größer die anzahl der werte, die du aufsummierst, desto extremer wird die kurve in der mitte groß und an den aussenseiten klein. achte aber darauf, dass Msleep einen int erwartet. ein int darf einen gesamtwert von 32000 (bissl mehr ist es, aber nicht viel) nicht überschreiten. nimm also einen long, addiere 10-20 werte, teile ihn durch die anzahl der werte, dann gib weiter an Msleep. der mittelwerte über viele werte wird immer bei etwa 500 sein, wenn gerade viele kleine werte aus dem zufallsgenerator kommen dann drunter, oder eben drüber bei großen werten.


aber wie hast du eigentlich den zufallsgenerator realisiert?

M1.R
20.06.2007, 11:11
nim die summe von 10 zufallszahlen. die mittleren werte der summe (ca 5000) werden sich häufen, da gleichmässig viele hohe und niedrige werte kommen und sich so ausgleichen. die chance, dass viele niedrige werte kommen, (kurze wartezeit) oder dass viele hohe werte kommen (lange wartezeit) ist geringer, als dass sowohl hohe als auch niedrige werte kommen (mittlere wartezeit).

je größer die anzahl der werte, die du aufsummierst, desto extremer wird die kurve in der mitte groß und an den aussenseiten klein. achte aber darauf, dass Msleep einen int erwartet. ein int darf einen gesamtwert von 32000 (bissl mehr ist es, aber nicht viel) nicht überschreiten. nimm also einen long, addiere 10-20 werte, teile ihn durch die anzahl der werte, dann gib weiter an Msleep. der mittelwerte über viele werte wird immer bei etwa 500 sein, wenn gerade viele kleine werte aus dem zufallsgenerator kommen dann drunter, oder eben drüber bei großen werten.

Vielen Dank!




aber wie hast du eigentlich den zufallsgenerator realisiert?

Nicht ich, sondern: http://www.roboterclub-freiburg.de/asuro/zufall/zufall.html

Gruss
M.

goara
20.06.2007, 18:28
koenntest es au<ch mit nur 2 zufallszahlen mahcen... zb die gauskurve in 10 bereiche einteilen... dann ne zufallszahl von 0 - 100 generieren... die zahlen dann nahc gausvertielung dne bereichen zuordnen.. zb. bereiche ganz aussen zahl 0 und 100 bereich eins weiter drinne 1-3 noch eins weiter drinne 4-10 usw.... und dann den zweiten durchlauf die genue zahl in dem bereich bestimmen,.. ist dann zwar keine perfekte gauskurve, sondern sowas eckiges, aber shcon ganz gut angenähert....

robo.fr
20.06.2007, 23:58
Deine Idee ist gar nich so schlecht. Ich bringe es mal auf einen einfachen Punkt:

uint8_t zufall();

x=zufall();
if(x<25) then "mach was"

Wahrscheinlichkeit für "mach was" = 10%

M1.R
21.06.2007, 00:14
Hallo goara und robo,

so wie ihr vorschlagt (Bereichseinteilung) habe ich es bisher schon gemacht. Diese Methode ist aber eher für eine begrenzte kleine Anzahl von Möglichkeiten geeignet.
Dalmators Gauß-Methode ist geeignet für eine "unbegrenzte" (=max 256) Anzahl von Möglichkeiten.

Gruss M.

M1.R
22.06.2007, 21:54
Hallo,

vielen Dank für eure guten Tipps!
Großen Dank auch an den Verfasser des Zufallsgenerators!

Hier mal ein kleines Programm, in dem die beiden Methoden "Bereich" und "Gauss" verwendet werden.

Die StatusLED soll mit der Wahrscheinlichkeit von ca. 10% aus sein,
mit der Wahrscheinlichkeit von ca. 20% gelb leuchten,
mit der Wahrscheinlichkeit von ca. 30% rot leuchten,
mit der Wahrscheinlichkeit von ca. 40% grün leuchten.
Gleichzeitig sollen die BackLEDs mit jew. 25% Wahrscheinlichkeit aus, links an, rechts an oder beide an sein.
Die jeweilige Dauer soll zwischen 0 und 2 sec. liegen mit einer Häufung um 1 sec. rum.

Soweit ich das beurteilen kann, scheint es auch zu klappen.

Gruss
M.




/************************************************** *************************
* zufall LED *
************************************************** *************************/

#include "asuro.h"


int i; //zähler
unsigned int data[2]; //odo
unsigned int zuf; //zufall


//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------

//
// uint8_t zufall()
//
// Liefert eine 8Bit Pseudozufallszahl zurück,
// die Zahlenfolge wiederholt sich spätestens nach 65535 Aufrufen
//

uint8_t zufall()
{
static uint16_t startwert=0x0AA;

uint16_t temp;
uint8_t n;

for(n=1;n<8;n++)
{
temp = startwert;
startwert=startwert << 1;

temp ^= startwert;
if ( ( temp & 0x4000 ) == 0x4000 )
{
startwert |= 1;
}
}

return (startwert);
}

//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------


uint8_t zufallodo()
{
static uint16_t startwert=0x0AA;

uint16_t temp;
uint8_t n;

for(n=1;n<8;n++)
{
temp = startwert;
startwert=startwert << 1;

temp ^= startwert;
if ( ( temp & 0x4000 ) == 0x4000 )
{
startwert |= 1;
}
}
BackLED(OFF,OFF);
OdometrieData(data); // aktuelle Helligkeitswerte der
startwert^= data[0];

return (startwert);
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------




int main(void)

{
Init();


// 3 sec "Anfangs-Zufallszahl"

StatusLED(OFF);
BackLED(OFF,OFF);

for(i=1;i<100;i++)
{
zuf = zufallodo();
Msleep(10);
}

Msleep(2000);





while (1)
{
StatusLED(OFF);
BackLED(OFF,OFF);

//bereich

zuf = zufall(); // Zufallszahlen zw. 0 und 255

if ( zuf < 25 ) // ca. 10% aus
{
StatusLED(OFF);
}

else if ( (zuf >= 25) && (zuf < 75) ) // ca. 20% gelb
{
StatusLED(YELLOW);
}

else if ( (zuf >= 75) && (zuf < 150) ) // ca. 30% rot
{
StatusLED(RED);
}

else if ( zuf >= 150 ) // ca. 40% grün
{
StatusLED(GREEN);
}

//bereich

zuf = zufall(); // Zufallszahlen zw. 0 und 255
zuf = zuf / 64; // Zufallszahlen zw. 0 und 3


if ( zuf == 0 ) // 25% beide aus
{
BackLED(OFF,OFF);
}

else if ( zuf == 1 ) // 25% links an - rechts aus
{
BackLED(ON,OFF);
}

else if ( zuf == 2 ) // 25% links aus - rechts an
{
BackLED(OFF,ON);
}

else if ( zuf == 3 ) // 25% beide an
{
BackLED(ON,ON);
}

// "gauss" dauer zwischen 0 und 2 sec mit häufung um 1 sec

for(i=1;i<=10;i++) // zahlen von 0 bis 2550
{
zuf = zuf + zufall();
}
zuf = (zuf * 4); // zahlen von 0 bis 10200
zuf = (zuf / 5); // zahlen zw 0 und 2040

Msleep(zuf);

}


while (1);
return 0;
}

damaltor
22.06.2007, 23:52
sehr gut... damit könnte man den kleinen fast emnschlich werdne lassen... =)

Sternthaler
24.06.2007, 00:10
Klasse Idee und Mathematik,
habe ich mal sofort etwas geändert und auch die Motoren mit in's Spiel genommen.

Ich bin ein Fan von blinkenden LED's :-)



/************************************************** ***************************
* zufall LED *
************************************************** ***************************/

#include "asuro.h"


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//
// uint8_t zufall ()
//
// Liefert eine 8-Bit Pseudozufallszahl zurück,
// die Zahlenfolge wiederholt sich spätestens nach 65535 Aufrufen.
//
unsigned char zufall ()
{
static unsigned int startwert = 0x0AA;
unsigned int temp;
unsigned char n;

for (n = 1; n < 8; n++)
{
temp = startwert;
startwert = startwert << 1;
temp ^= startwert;
if ((temp & 0x4000) == 0x4000)
startwert |= 1;
}

return (startwert);
}


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int main (void)
{
int i; //Zähler
unsigned int data [2]; //Odo
unsigned int zuf; //Zufall
unsigned char dirlinks, dirrechts;
unsigned char speedlinks, speedrechts;

Init ();

StatusLED (OFF);

/* Zufaellige Zeit fuer "Anfangs-Zufallszahl" */
zuf = zufall ();
OdometrieData (data); // aktuelle Odometriewerte
zuf ^= data [0];
for (i = 1; i < zuf; i++)
zufall ();

while (1)
{
StatusLED (OFF);
BackLED (OFF, OFF);

/* Bereich StatusLED */
zuf = zufall (); // Zufallszahlen zw. 0 und 255
if (zuf < 25)
StatusLED (OFF); // ca. 10% aus
else if (zuf < 75)
StatusLED (YELLOW); // ca. 20% gelb
else if (zuf < 150)
StatusLED (RED); // ca. 30% rot
else
StatusLED (GREEN); // ca. 40% grün

/* Bereich BackLED */
zuf = zufall (); // Zufallszahlen zw. 0 und 255
if (zuf < 64)
BackLED (OFF, OFF); // 25% beide aus
else if (zuf < 128)
BackLED (ON, OFF); // 25% links an - rechts aus
else if (zuf < 192)
BackLED (OFF, ON); // 25% links aus - rechts an
else
BackLED (ON, ON); // 25% beide an

/* Bereich FrontLED */
zuf = zufall (); // Zufallszahlen zw. 0 und 255
if (zuf < 204)
FrontLED (OFF); // 80% aus
else
FrontLED (ON); // 20% an

/* Richtung */
zuf = zufall ();
if (zuf < 216)
dirlinks = FWD; // 85% vorwaerts
else if (zuf < 230)
dirlinks = BREAK; // 5% stop
else
dirlinks = RWD; // 10% rueckwaerts

zuf = zufall ();
if (zuf < 216)
dirrechts = FWD; // 85% vorwaerts
else if (zuf < 230)
dirrechts = BREAK; // 5% stop
else
dirrechts = RWD; // 10% rueckwaerts
MotorDir (dirlinks, dirrechts);

/* Geschwindigkeit */
zuf = zufall ();
if (zuf < 128)
speedlinks = 130; // 50% langsam
else if (zuf < 204)
speedlinks = 170; // 30% mittel
else
speedlinks = 200; // 20% schnell

zuf = zufall ();
if (zuf < 128)
speedrechts = 130; // 50% langsam
else if (zuf < 204)
speedrechts = 170; // 30% mittel
else
speedrechts = 200; // 20% schnell
MotorSpeed (speedlinks, speedrechts);

/* "gauss" dauer zwischen 0 und 2 sec mit häufung um 1 sec */
zuf = 0;
/*
for (i = 1; i <= 10; i++) // zahlen von 0 bis 2550
zuf += zufall ();
zuf *= 4; // zahlen von 0 bis 10200
zuf /= 5; // zahlen von 0 bis 2040
*/
/* "gauss" dauer zwischen 0 und 2 sec mit geringerer häufung um 1 sec */
for (i = 1; i <= 4; i++) // zahlen von 0 bis 1020
zuf += zufall ();
zuf *= 2; // zahlen von 0 bis 2040

Msleep(zuf);
}

return 0;
}