Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Zufallszaheln erzeugen

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 <
010
23.08.2005, 13:00 Uhr
Crack



Sers erstma

die Lösung ist ganz kompliziert, da mam ohne Hilfe nicht drauf kommt.
Habs auch nur in der Schule gelernt (Berufsfachschule für Datenverarbeitung und Wirtschaft).

_____________________________________
Lösung:

C++:
int init_zufallszahl(void)
{
    unsigned long tp;
    
    time(&tp);
    srand(tp);
    rand();
    return 0;
}

int zufallszahl(int untergrenze, int obergrenze)
{
    float zufallszahl;

    zufallszahl=rand();
    zufallszahl/=RAND_MAX;
    zufallszahl*=(obergrenze-untergrenze +1);
    zufallszahl+=untergrenze;
    return (int) zufallszahl;
}



mod edit: benutze CPP Tags selber

Dieser Post wurde am 23.08.2005 um 15:10 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
23.08.2005, 13:10 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


umständlich machs halt so:


C++:

void init_random()
{
  srand((unsigned)time(NULL));
}

void random(int min, int max)
{
   return rand() % (max-min) + min;
}



das ist das einfachste und schnellste.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
23.08.2005, 13:11 Uhr
Crack



Sers erstma

die Lösung ist ganz kompliziert, da mam ohne Hilfe nicht drauf kommt.
Habs auch nur in der Schule gelernt (Berufsfachschule für Datenverarbeitung und Wirtschaft).

_____________________________________
Lösung:

C++:
#include <stdio.h>
#include <time.h>  /* für time(&unsigned_long_variable) nötig) */
#include <stdlib.h> /* für rand() nötig */

#define MAX 1
#define MIN 100

int init_zufallszahl(void)
{
    unsigned long tp;
    
    time(&tp);
    srand(tp);
    rand();
    return 0;
}

int zufallszahl(int untergrenze, int obergrenze)
{
    float zufallszahl;

    zufallszahl=rand();
    zufallszahl/=RAND_MAX;
    zufallszahl*=(obergrenze-untergrenze +1);
    zufallszahl+=untergrenze;
    return (int) zufallszahl;
}

int main(void)
{
    int Zufallszahl;
    init_zufallszahl();
    Zufallszahl=zufallszahl(MIN,MAX);
    printf("Zufallszahl = %d\n", Zufallszahl);
    return 0;
}


_____________________________________

Kurze erläuterung:
Dieser Zufallsgenerator generiert die Zufallszahl aus der Systemzeit

Für weitere Fragen stehe ich gerne zu verfügung!

mod edit: benutze die CPP Tags selber!

Dieser Post wurde am 23.08.2005 um 15:10 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
23.08.2005, 13:39 Uhr
virtual
Sexiest Bit alive
(Operator)


@Crack

Sorry, aber der Code ist schrott (wenn Du ihn so gelernt hast, dann tritt mal Deinem Dozent):

1. Zunächstmal ist zufallszahl ein Float und hat damit eine Rechengenauigkeit von etwa 7 Dezimalstellen. Auf gängigen Betriebssystemen ist aber RAND_MAX==INT_MAX und damit größer als 2 Milliarden und damit werden also 10 Stellige Zahlen produziert. Die Speicherung von dem Ergebnis in zufallszahl vergisst somit also 3 Dezimalstellen oder genauer gesagt mindestens 6 bits der Zufallszahl (32 Bit betriebssysteme).

2. Liegen untergrenze und Obergrenze etwas weiter auseinander, zB obergrenze==1500000000 und untegrenze==-1500000000, so ist das Ergebnis nicht mehr das gewünschte, weil der Ausdruck in der dritt letzten Zeile einen Overflow generiert.

3. Die Routine ist ziemliche Augenwischerei, weil sie einfach die Zufallszahlen linear auf den Bereich [0; 1[ mappt und anschließend (mit oben erwähnten Bitverlust wieder zurückmappt. Dh selbst wenn jetzt RAND_MAX wesentlich kleiner wäre als der Bereich von int, so würde man nun vor dem Problem stehen, daß die Zahlen zwischen Unter- und Obergrenze nicht mehr gleichverteilt wären, sondern in sehr regelmäßigen Abständen zahlenblöcke zu finden wären, welche niemals gezogen würden.

4. Wie bereits unter (1) erwähnt ist auf den meisten modernen Systemen RAND_MAX identisch mit dem max. möglichen integer wert. Von daher sollte erstmal geprüft werden, ob man wirklich irgendwelche Algorithmen benötigt, um den Wertebereich des Zufallsgenerators zu vergrößern.

5. Der kern des Problems wird überhaupt nicht angefasst: Der Kern des Problems liegt darin, daß man unterschiedliche Strategien fahren muß, je nachdem ob der Abstand zwischen ober- und untergrenze kleiner oder größer als RAND_MAX ist.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
23.08.2005, 13:53 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


ansonsten erwartet time nen time_t
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
23.08.2005, 14:01 Uhr
virtual
Sexiest Bit alive
(Operator)


@Crack
Ich möchte mein Post von vorhin dahingehend präzisieren, daß der Algorithmus dann benutzbar ist, wenn unter und obergrenze nah beieinanderliegen.

Ich möchte nochmal kurz auf das Problem speziell bei kleinen Zahlen zusprechen kommen, also zB eine Würfelsimulation:
Nimmt man vereinfachend an, daß RAND_MAX=9 sei, also der Zufallsgenerator Zahlen zwischen 0 und 9 produziert, so ist sofort einleuchtend, daß diese Modulovariante zu Problemen führt:

C++:
int wuerfel() {
    return rand()%6 + 1;
}


Der grund: Folgende Tablle zeigt in der ersten Spale den Rückgabewert von rand und in der zweiten Splate den von wuerfel:

Code:
0 1
1 2
2 3
3 4
4 5
5 6
6 1
7 2
8 3
9 4


Man erkennt leicht, daß also die zahlen 1-4 mit 20% Wahrscheinlichkeit, die Zahlen 5-6 nur mit 10% wahrscheinlichkeit gewürfelt werden.

Dieses Problem kann stärker und weniger stark ausgeprägt sein: Ist n die Anzahl der Würfelflächen, dann
1. gibt es überhaupt kein Problem, wenn (RAND_MAX+1) ein Vielfaches von n ist
2. wird das Problem größer, je größer der Quotient von n/RAND_MAX ist
3. wird das Problem kleiner, je kleiner der Quotient von n/RAND_MAX ist

Letztlich wird man mit der Modulo variante bei einem realistischen RAND_MAX=2,1 Milliarde und m=6 meistens keine messbaren Probleme bekommen. Dh für triviale Anwendungen, wo eben n/RAND_MAX "klein" ist, hat man auch keine Probleme.

Die von Crack angegegebene Variante ist sinnvoll für kleine n. Je größer n wird, desto heftiger ist jedoch ihr versagen.

Man kann IMHO folgende Lösung nehmen: man Schreibt n als eine Summe von zweierpotenzen auf. Etwa: 6 = 4+2
Dann geht man hin und brechnet den Wuerfel so:

C++:
int wuerfel() {
    return rand()%4 + rand()%2 +1;
}


Das geht aber nur für n < RAND_MAX. Ist n>RAND_MAX muß man andere Strategien fahren.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: