Forum: PC-Programmierung random liefert ungültige Werte (ausserhalb bereich)


von Mark (Gast)


Lesenswert?

hallo, ich möchte mit rand() zufallswerte in einem bereich erstellen, 
allerdings liefert mir die Funktion auch werte ausserhalb des bereichs
1
#include <iostream>
2
#include <stdlib.h>
3
#include <time.h>
4
5
int main(void){
6
...
7
  time_t t;
8
  time(&t);
9
10
  srand((unsigned int)t);
11
...
12
  n_guess = rand() % 20 + 10;
13
...
14
}


n_guess liefert auch werte über 20.


eigentlich ja auch richtig, wenn ich das richtig verstanden habe
n_guess = rand() % 20 liefert eine Zufallszahl zwischen 0 und 20. wenn 
ich dann noch 10 dazu addiere, kann es sein, dass ich über 20 komme.

setze ich die 20 + 10  in klammern, kämen ja werte zwischen 0 und 30 
heraus. Aber in allen beispielen die ich gesehen habe, ist das so 
geschrieben.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Mark schrieb:
> n_guess = rand() % 20 liefert eine Zufallszahl zwischen 0 und 20.

Nein, zwischen 0 und 19.

Mit Deiner Addition von 10 erhältst Du Werte im Bereich von 10 bis 29.

Was war jetzt nochmal Dein Problem?

Was willst Du erreichen, und was verstehst Du nicht?

von Michael U. (amiga)


Lesenswert?

Hallo,

Du hast vergessen, Deinen gewünschten Beeich anzugeben...

%20 ist eine Modulo-Division und leifert somit den Rest.
Bei Divison durch 20 kann der Rest also zwischen 0 und 19 liegen.
Wenn Du dann 10 addierst bist Du im Bereich 10...29.

Wenn Du 10...19 haben willst, solltest Du eben %10 (liefert 0...9) + 10 
rechnen (10...19).

Gruß aus Berlin
Michael

von Mark (Gast)


Lesenswert?

Es ist einfach die Schreibweise, die mich durcheinander bringt, da 'ich' 
die grenzen so nicht sofort erkenne.
wenn ich jetzt mit variablen arbeiten möchte
upper_bound = 20
lower_bound = 10
und ich möchte eine Zahl zwischen den Zahlen (also von 11 bis 19) muss 
ich ja schreiben
1
n_guess = rand() % (upper_bound - lower_bound - 1) + (lower_bound + 1);

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn Du Zahlen im Wertebereich [11..19] haben möchtest, ist es unnötig 
umständlich, "upper_" und "lower_bound" im Wertebereich ]10..20[ 
anzugeben.

von Rolf M. (rmagnus)


Lesenswert?

Mark schrieb:
> n_guess = rand() % 20 + 10;
> ...
> }
>
> n_guess liefert auch werte über 20.
>
> eigentlich ja auch richtig, wenn ich das richtig verstanden habe
> n_guess = rand() % 20 liefert eine Zufallszahl zwischen 0 und 20.

rand() liefert eine Zufallszahl im Bereich 0 bis RAND_MAX. Alles andere 
sind einfach arithmetische Berechnungen.

Mark schrieb:
> Es ist einfach die Schreibweise, die mich durcheinander bringt, da 'ich'
> die grenzen so nicht sofort erkenne.

Du gibst mit
1
  n_guess = rand() % 20 + 10;
ja auch keine Grenzen für rand() an, sondern führst einfach noch zwei 
Berechnungen mit dem Ergebnis durch. a % b liefert den Modulo, also den 
Rest der Ganzzahldivision aus a und b, und das + ist einfach nur eine 
gewöhnliche Addition.

von Franz-Ferdinand Flossenreiter (Gast)


Lesenswert?

Schreibe dir doch einfache eine Funktion, der du die obere und untere 
Grenze übergeben kannst und die diese kleine Berechnung ausführt. Die 
Funktion rufst du dann mit irgendwas_rand(11, 19) oder was auch immer 
auf und siehst sofort, was los ist.

von Mark (Gast)


Lesenswert?

Franz-Ferdinand Flossenreiter schrieb:
> Schreibe dir doch einfache eine Funktion, der du die obere und untere
> Grenze übergeben kannst und die diese kleine Berechnung ausführt. Die
> Funktion rufst du dann mit irgendwas_rand(11, 19) oder was auch immer
> auf und siehst sofort, was los ist.

So habe ich es auch gemacht

von Dr. Sommer (Gast)


Lesenswert?

Da du ja C++ verwendest, kannst du die C++ Random Funktionen nutzen, 
anstelle der alten C-Funktionen. Diese bieten u.a. eine einfachere 
Einstellung des Bereichs:
1
#include <iostream>
2
#include <random>
3
4
int main() {
5
  std::mt19937 gen;
6
  std::uniform_int_distribution<int> dist (10, 20);
7
  
8
  for (int i = 0; i < 100; ++i) {
9
    std::cout << dist (gen) << std::endl;
10
  }
11
  
12
  return 0;
13
}

Dies hat gegenüber der Version mit rand() und % den großen Vorteil, dass 
die Werte gleichverteilt sind, d.h. die Wahrscheinlichkeit dass 10 
auftritt ist gleich der Wahrscheinlichkeit dass 11 auftritt ... usw. Das 
ist bei "rand () % X" nur der Fall, wenn "X % RAND_MAX" gleich 0 ist.

Sieh z.B.
http://en.cppreference.com/w/cpp/numeric/random
http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution

von Dr. Sommer (Gast)


Lesenswert?


von Rainer V. (rudi994)


Lesenswert?

Dr. Sommer schrieb:
> Werte gleichverteilt... Das ist bei "rand () % X" nur der Fall,
> wenn "X % RAND_MAX" gleich 0 ist.

> Äh, vertan. Es muss "RAND_MAX % X == X-1" sein

Stimmt! Ersteres ist falsch. Letzteres ebenso. Denn RAND_MAX ist die 
größte Zufallszahl, die rand() liefern kann (und tatsächlich öfter mal 
zurückgibt). Obergrenze für rand() ist RAND_MAX+1, das ist auch die 
Anzahl Werte einschl. Null, die rand() liefern kann. X ist die Anzahl 
der Werte im gewünschten Zahlenbereich von Null bis X-1. X ist die 
Obergrenze des Bereiches. Die Obergrenzen RAND_MAX+1 und X werden selbst 
nie erreicht. Die Zufallszahlen im gewünschten Bereich sind gleichmäßig 
verteilt, wenn (RAND_MAX+1) % X == 0 ist und rand() bei wiederholten 
Aufrufen auch tatsächlich gleichmäßig verteilte Werte liefert.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Rainer V. schrieb:
>> Äh, vertan. Es muss "RAND_MAX % X == X-1" sein
>
> Stimmt! Ersteres ist falsch. Letzteres ebenso.
> ...
> Die Zufallszahlen im gewünschten Bereich sind gleichmäßig
> verteilt, wenn (RAND_MAX+1) % X == 0 ist

Sind die Bedingungen

  RAND_MAX % X == X-1

und

  (RAND_MAX+1) % X == 0

nicht äquivalent?

von Rainer V. (rudi994)


Lesenswert?

Yalu X. schrieb:
> nicht äquivalent?

Ja stimmt, ist äquivalent. Allerdings wäre mir RAND_MAX % X == X-1 
niemals als Erstes zum Thema eingefallen :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.