Zufällige Ganzzahl aus einem Bereich generieren


157

Ich benötige eine Funktion, die eine zufällige Ganzzahl in einem bestimmten Bereich (einschließlich Randwerten) generiert. Ich habe keine unangemessenen Qualitäts- / Zufallsanforderungen, ich habe vier Anforderungen:

  • Ich brauche es, um schnell zu sein. Mein Projekt muss Millionen (oder manchmal sogar Dutzende Millionen) Zufallszahlen generieren, und meine aktuelle Generatorfunktion hat sich als Engpass erwiesen.
  • Ich brauche es, um einigermaßen einheitlich zu sein (die Verwendung von rand () ist vollkommen in Ordnung).
  • Die Min-Max-Bereiche können zwischen <0, 1> und <-32727, 32727> liegen.
  • es muss siedbar sein.

Ich habe derzeit folgenden C ++ - Code:

output = min + (rand() * (int)(max - min) / RAND_MAX)

Das Problem ist, dass es nicht wirklich einheitlich ist - max wird nur zurückgegeben, wenn rand () = RAND_MAX ist (für Visual C ++ ist es 1/32727). Dies ist ein großes Problem für kleine Bereiche wie <-1, 1>, in denen der letzte Wert fast nie zurückgegeben wird.

Also griff ich nach Stift und Papier und fand die folgende Formel (die auf dem ganzzahligen Rundungstrick (int) (n + 0,5) aufbaut):

Geben Sie hier die Bildbeschreibung ein

Aber es gibt mir immer noch keine gleichmäßige Verteilung. Wiederholte Läufe mit 10000 Proben ergeben ein Verhältnis von 37:50:13 für die Werte -1, 0,1.

Könnten Sie bitte eine bessere Formel vorschlagen? (oder sogar ganze Pseudozufallszahlengeneratorfunktion)



3
@ Bill MaGriff: Ja. Es hat das gleiche Problem. Eine vereinfachte Version lautet: Wie können Sie 10 Bonbonstücke gleichmäßig auf 3 Kinder verteilen (ohne die Bonbons zu zerbrechen)? Die Antwort lautet: Sie können nicht - Sie müssen jedem Kind drei geben und nur niemandem den zehnten.
Jerry Coffin

5
Haben Sie sich Boost.Random angesehen ?
Fred Nurk

3
Überprüfen Sie den Andrew Koenig Artikel "Ein einfaches Problem, das fast nie richtig gelöst wird": drdobbs.com/blog/archives/2010/11/a_simple_proble.html
Gene Bushuyev

1
@Gene Bushuyev: Sowohl Andrew als auch ich beschäftigen uns schon seit einiger Zeit mit diesem Thema. Siehe: groups.google.com/group/comp.lang.c++/browse_frm/thread/… und: groups.google.com/group/comp.os.ms-windows.programmer.tools.mfc/…
Jerry Coffin

Antworten:


105

Eine schnelle, etwas bessere als Ihre, aber immer noch nicht richtig gleichmäßig verteilte Lösung ist

output = min + (rand() % static_cast<int>(max - min + 1))

Außer wenn die Größe des Bereichs eine Potenz von 2 ist, erzeugt dieses Verfahren unabhängig von der Qualität von voreingenommene ungleichmäßig verteilte Zahlenrand() . Lesen Sie dies bitte, um einen umfassenden Test der Qualität dieser Methode zu erhalten .


2
Danke, das scheint mir aus schnellen Tests gut genug zu sein - seine Verteilung für -1, 0, 1 ist fast 33:33:33.
Matěj Zábský

3
Es wird immer der Maximalwert zurückgegeben. Vermisse ich hier etwas? : |
Rohan-Patel

15
rand()sollte in C ++ als schädlich angesehen werden, gibt es viel bessere Möglichkeiten, etwas zu erhalten, das gleichmäßig verteilt und tatsächlich zufällig ist.
Mgetz

1
Gibt es wirklich 100% der Zeit eine korrekte Zahl innerhalb des Bereichs zurück? Ich habe hier eine andere Stackoverflow-Antwort gefunden, die Rekursion verwendet, um es "richtig" zu machen: stackoverflow.com/a/6852396/623622
Czarek Tomczak

2
Da es sich um eine hoch bewertete (als erwünschte) Antwort handelt, die für viele neue Leser als verlässliche Informationsquelle erscheint, ist es meiner Meinung nach sehr wichtig, die Qualität und die potenziellen Gefahren dieser Lösung zu erwähnen. Deshalb habe ich eine Bearbeitung vorgenommen.
Plasmacel

296

Die einfachste (und damit beste) C ++ - Antwort (unter Verwendung des 2011er Standards) lautet

#include <random>

std::random_device rd;     // only used once to initialise (seed) engine
std::mt19937 rng(rd());    // random-number engine used (Mersenne-Twister in this case)
std::uniform_int_distribution<int> uni(min,max); // guaranteed unbiased

auto random_integer = uni(rng);

Das Rad muss nicht neu erfunden werden. Sie müssen sich keine Sorgen um Voreingenommenheit machen. Sie müssen sich keine Sorgen machen, Zeit als Zufallssamen zu verwenden.


1
Heutzutage sollte dies die Antwort sein . Referenz zur Erzeugung von Pseudozufallszahlen für weitere Funktionen.
Alextoind

8
Ich stimme dem "einfachsten" (und idiomatischsten) zu, nicht dem "besten". Leider gibt der Standard keine Garantie dafür random_device, was in einigen Fällen vollständig gebrochen werden kann . Darüber hinaus ist es mt19937zwar eine sehr gute Allzweckwahl, aber nicht der schnellste Generator guter Qualität (siehe diesen Vergleich ) und daher möglicherweise nicht der ideale Kandidat für das OP.
Alberto M

1
@AlbertoM Leider liefert der Vergleich, auf den Sie sich beziehen, nicht genügend Details und ist nicht reproduzierbar, was ihn zweifelhaft macht (außerdem stammt er aus dem Jahr 2015, während meine Antwort auf das Jahr 2013 zurückgeht). Es mag richtig sein, dass es bessere Methoden gibt (und hoffentlich in Zukunft minstdeine solche Methode geben wird), aber das ist ein Fortschritt. Was die schlechte Implementierung von random_device- betrifft, ist das schrecklich und sollte als Fehler angesehen werden (möglicherweise auch des C ++ - Standards, wenn es dies zulässt).
Walter

1
Ich stimme dir vollkommen zu; Ich wollte Ihre Lösung nicht per se kritisieren, sondern nur den Gelegenheitsleser warnen, dass die endgültige Antwort in dieser Angelegenheit trotz der Versprechen von C ++ 11 noch zu schreiben ist. Ich werde ab 2015 einen Überblick über das Thema als Antwort auf eine verwandte Frage veröffentlichen .
Alberto M

1
Das ist "am einfachsten"? Könnten Sie näher erläutern, warum das eindeutig viel Einfachere rand()keine Option ist und es für die unkritische Verwendung wie das Generieren eines zufälligen Pivot-Index von Bedeutung ist? Außerdem muss ich Sorge haben über den Bau random_device/ mt19937/ uniform_int_distributionin einer engen Schleife / inlined Funktion? Sollte ich es vorziehen, sie weiterzugeben?
bluenote10

60

Wenn Ihr Compiler C ++ 0x unterstützt und die Verwendung für Sie eine Option für Sie ist, entspricht der neue Standardheader <random>wahrscheinlich Ihren Anforderungen. Es hat eine hohe Qualität, uniform_int_distributiondie minimale und maximale Grenzen akzeptiert (einschließlich nach Bedarf), und Sie können zwischen verschiedenen Zufallszahlengeneratoren wählen, um diese Verteilung anzuschließen.

Hier ist Code, der eine Million Zufallszahlen erzeugt, die intgleichmäßig in [-57, 365] verteilt sind. Ich habe die neuen Standardfunktionen verwendet <chrono>, um die Zeit zu bestimmen , da die von Ihnen erwähnte Leistung ein wichtiges Anliegen für Sie ist.

#include <iostream>
#include <random>
#include <chrono>

int main()
{
    typedef std::chrono::high_resolution_clock Clock;
    typedef std::chrono::duration<double> sec;
    Clock::time_point t0 = Clock::now();
    const int N = 10000000;
    typedef std::minstd_rand G;
    G g;
    typedef std::uniform_int_distribution<> D;
    D d(-57, 365);
    int c = 0;
    for (int i = 0; i < N; ++i) 
        c += d(g);
    Clock::time_point t1 = Clock::now();
    std::cout << N/sec(t1-t0).count() << " random numbers per second.\n";
    return c;
}

Für mich (2,8 GHz Intel Core i5) druckt dies aus:

2.10268e + 07 Zufallszahlen pro Sekunde.

Sie können den Generator festlegen, indem Sie ein int an seinen Konstruktor übergeben:

    G g(seed);

Wenn Sie später feststellen, dass intdies nicht den Bereich abdeckt, den Sie für Ihre Distribution benötigen, können Sie dies beheben, indem Sie Folgendes ändern uniform_int_distribution(z. B. in long long):

    typedef std::uniform_int_distribution<long long> D;

Wenn Sie später feststellen, dass der minstd_randGenerator nicht hoch genug ist, kann er auch problemlos ausgetauscht werden. Z.B:

    typedef std::mt19937 G;  // Now using mersenne_twister_engine

Eine getrennte Kontrolle über den Zufallszahlengenerator und die Zufallsverteilung kann ziemlich befreiend sein.

Ich habe auch die ersten 4 "Momente" dieser Verteilung berechnet (nicht gezeigt) (unter Verwendung minstd_rand) und sie mit den theoretischen Werten verglichen , um die Qualität der Verteilung zu quantifizieren:

min = -57
max = 365
mean = 154.131
x_mean = 154
var = 14931.9
x_var = 14910.7
skew = -0.00197375
x_skew = 0
kurtosis = -1.20129
x_kurtosis = -1.20001

(Das x_Präfix bezieht sich auf "erwartet")


3
Diese Antwort könnte ein kurzes Zusammenfassungscode-Snippet verwenden, das nur den Code anzeigt, der tatsächlich benötigt wird, um eine zufällige Ganzzahl aus einem Bereich zu generieren.
Arekolek

Das Problem wird dadurch erleichtert, dass sich Min und Max der Verteilung nie ändern. Was wäre, wenn Sie dbei jeder Iteration unterschiedliche Grenzen erstellen müssten? Wie viel würde es die Schleife verlangsamen?
quant_dev

15

Teilen wir das Problem in zwei Teile:

  • Generieren Sie eine Zufallszahl nim Bereich von 0 bis (max-min).
  • Fügen Sie dieser Zahl min hinzu

Der erste Teil ist offensichtlich der schwierigste. Nehmen wir an, dass der Rückgabewert von rand () vollkommen einheitlich ist. Wenn Sie Modulo verwenden, werden die ersten (RAND_MAX + 1) % (max-min+1)Zahlen verzerrt. Wenn wir also auf magische Weise verändern könnten RAND_MAXzu RAND_MAX - (RAND_MAX + 1) % (max-min+1), es würde nicht mehr Bias.

Es stellt sich heraus, dass wir diese Intuition verwenden können, wenn wir bereit sind, Pseudo-Nichtdeterminismus in die Laufzeit unseres Algorithmus einzubeziehen. Immer wenn rand () eine zu große Zahl zurückgibt, fragen wir einfach nach einer anderen Zufallszahl, bis wir eine erhalten, die klein genug ist.

Die Laufzeit wird nun geometrisch verteilt mit Erwartungswert , 1/pwo pist die Wahrscheinlichkeit, eine klein genug Zahl auf dem ersten Versuch zu bekommen. Da RAND_MAX - (RAND_MAX + 1) % (max-min+1)immer weniger als ist (RAND_MAX + 1) / 2, wissen wir das p > 1/2, so dass die erwartete Anzahl von Iterationen für jeden Bereich immer weniger als zwei beträgt. Mit dieser Technik sollte es möglich sein, auf einer Standard-CPU in weniger als einer Sekunde zig Millionen Zufallszahlen zu generieren.

BEARBEITEN:

Obwohl das oben Gesagte technisch korrekt ist, ist die Antwort von DSimon in der Praxis wahrscheinlich nützlicher. Sie sollten dieses Zeug nicht selbst implementieren. Ich habe viele Implementierungen von Ablehnungsstichproben gesehen und es ist oft sehr schwierig zu sehen, ob es korrekt ist oder nicht.


Der Vollständigkeit halber : Dies ist Rejection Sampling .
Etarion

3
Unterhaltsame Tatsache: Joel Spolsky erwähnte einmal eine Version dieser Frage als Beispiel dafür, was StackOverflow gut beantworten konnte. Ich schaute durch die Antworten auf der Website beteiligt Verwerfungsmethode zu dieser Zeit und jedes einzelne eines falsch war.
Jørgen Fogh

13

Wie wäre es mit dem Mersenne Twister ? Die Boost-Implementierung ist recht einfach zu bedienen und in vielen realen Anwendungen gut getestet. Ich habe es selbst in mehreren akademischen Projekten wie künstlicher Intelligenz und evolutionären Algorithmen verwendet.

Hier ist ihr Beispiel, in dem sie eine einfache Funktion zum Werfen eines sechsseitigen Würfels ausführen:

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/variate_generator.hpp>

boost::mt19937 gen;

int roll_die() {
    boost::uniform_int<> dist(1, 6);
    boost::variate_generator<boost::mt19937&, boost::uniform_int<> > die(gen, dist);
    return die();
}

Oh, und hier ist noch ein paar Zuhälter dieses Generators, falls Sie nicht überzeugt sind, dass Sie ihn über den weitaus minderwertigen verwenden sollten rand():

Der Mersenne Twister ist ein "Zufallszahlen" -Generator, der von Makoto Matsumoto und Takuji Nishimura erfunden wurde. Ihre Website enthält zahlreiche Implementierungen des Algorithmus.

Im Wesentlichen ist der Mersenne Twister ein sehr großes Schieberegister mit linearer Rückkopplung. Der Algorithmus arbeitet mit einem 19.937-Bit-Startwert, der in einem 624-Element-Array von 32-Bit-Ganzzahlen ohne Vorzeichen gespeichert ist. Der Wert 2 ^ 19937-1 ist eine Mersenne-Primzahl; Die Technik zur Manipulation des Samens basiert auf einem älteren "Twisting" -Algorithmus - daher der Name "Mersenne Twister".

Ein ansprechender Aspekt des Mersenne Twister ist die Verwendung von Binäroperationen - im Gegensatz zur zeitaufwändigen Multiplikation - zur Erzeugung von Zahlen. Der Algorithmus hat auch eine sehr lange Periode und eine gute Granularität. Es ist sowohl schnell als auch effektiv für nicht kryptografische Anwendungen.


1
Der Mersenne-Twister ist ein guter Generator, aber das Problem, mit dem er sich befasst, bleibt bestehen, unabhängig vom zugrunde liegenden Generator.
Jerry Coffin

Ich möchte Boost nicht nur für den Zufallsgenerator verwenden, da es (da mein Projekt eine Bibliothek ist) bedeutet, eine weitere Abhängigkeit in das Projekt einzuführen. Ich werde wahrscheinlich in Zukunft sowieso gezwungen sein, es zu benutzen, damit ich dann auf diesen Generator umsteigen kann.
Matěj Zábský

1
@ Jerry Sarg Welches Problem? Ich habe es angeboten, weil es alle seine Anforderungen erfüllt hat: Es ist schnell, es ist einheitlich (unter Verwendung der boost::uniform_intVerteilung), Sie können die Min-Max-Bereiche in alles umwandeln, was Sie möchten, und es ist setzbar.
Aphex

@mzabsky Ich würde mich wahrscheinlich nicht davon abhalten lassen, als ich meine Projekte zur Einreichung an meine Professoren senden musste. Ich habe nur die relevanten Boost-Header-Dateien eingefügt, die ich verwendet habe. Sie sollten nicht die gesamte 40-MB-Boost-Bibliothek mit Ihrem Code packen müssen. Natürlich ist dies in Ihrem Fall aus anderen Gründen wie dem Urheberrecht möglicherweise nicht möglich ...
Aphex

@Aphex Mein Projekt ist nicht wirklich ein wissenschaftlicher Simulator oder etwas, das eine wirklich gleichmäßige Verteilung benötigt. Ich habe den alten Generator 1,5 Jahre lang ohne Probleme verwendet. Ich habe die voreingenommene Verteilung erst bemerkt, als ich sie zum ersten Mal brauchte, um Zahlen aus einem sehr kleinen Bereich zu generieren (in diesem Fall 3). Die Geschwindigkeit ist jedoch immer noch ein Argument, um die Boost-Lösung in Betracht zu ziehen. Ich werde in der Lizenz nachsehen, ob ich meinem Projekt nur die wenigen benötigten Dateien hinzufügen kann - ich mag das "Checkout -> F5 -> einsatzbereit" so wie es jetzt ist.
Matěj Zábský

11
int RandU(int nMin, int nMax)
{
    return nMin + (int)((double)rand() / (RAND_MAX+1) * (nMax-nMin+1));
}

Dies ist eine Zuordnung von 32768 Ganzzahlen zu (nMax-nMin + 1) Ganzzahlen. Das Mapping ist ziemlich gut, wenn (nMax-nMin + 1) klein ist (wie in Ihrer Anforderung). Beachten Sie jedoch, dass die Zuordnung nicht funktioniert, wenn (nMax-nMin + 1) groß ist (z. B. können Sie 32768-Werte nicht mit gleicher Wahrscheinlichkeit 30000-Werten zuordnen). Wenn solche Bereiche benötigt werden, sollten Sie anstelle des 15-Bit-Rand () eine 32-Bit- oder 64-Bit-Zufallsquelle verwenden oder Rand () -Ergebnisse ignorieren, die außerhalb des Bereichs liegen.


Trotz seiner Unbeliebtheit verwende ich dies auch für meine nichtwissenschaftlichen Projekte. Einfach zu verstehen (Sie benötigen keinen Mathematik-Abschluss) und eine angemessene Leistung (Sie mussten nie einen Code damit profilieren). :) Bei großen Bereichen könnten wir wahrscheinlich zwei rand () -Werte aneinanderreihen und einen 30-Bit-Wert erhalten, mit dem wir arbeiten können (unter der Annahme von RAND_MAX = 0x7fff, dh 15 zufälligen Bits)
efotinis

Ändern Sie RAND_MAXdiese Option , (double) RAND_MAXum eine Ganzzahlüberlaufwarnung zu vermeiden.
Alex

4

Hier ist eine unvoreingenommene Version, die Zahlen generiert in [low, high]:

int r;
do {
  r = rand();
} while (r < ((unsigned int)(RAND_MAX) + 1) % (high + 1 - low));
return r % (high + 1 - low) + low;

Wenn Ihr Bereich relativ klein ist, gibt es keinen Grund, die rechte Seite des Vergleichs in der doSchleife zwischenzuspeichern.


IMO, keine der dort vorgestellten Lösungen ist wirklich viel besser. Seine schleifenbasierte Lösung funktioniert, ist aber wahrscheinlich ziemlich ineffizient, insbesondere für einen kleinen Bereich, wie er im OP diskutiert wird. Seine einheitliche Abweichungslösung erzeugt überhaupt keine einheitlichen Abweichungen. Es tarnt höchstens die mangelnde Einheitlichkeit.
Jerry Coffin

@ Jerry: Bitte überprüfen Sie die neue Version.
Jeremiah Willcock

Ich bin mir ein bisschen unsicher, ob das richtig funktioniert. Es mag sein, aber Korrektheit scheint mir zumindest nicht offensichtlich zu sein.
Jerry Coffin

@ Jerry: Hier ist meine Argumentation: Angenommen, der Bereich dient der [0, h)Einfachheit. Das Aufrufen rand()hat RAND_MAX + 1mögliche Rückgabewerte. wobei rand() % hkollabiert (RAND_MAX + 1) / hvon ihnen zu jedem der hAusgangswerte, mit der Ausnahme , dass (RAND_MAX + 1) / h + 1sie auf die Werte zugeordnet werden , die weniger als (RAND_MAX + 1) % h(wegen des letzten Teilzyklus durch die hAusgänge). Wir entfernen daher (RAND_MAX + 1) % hmögliche Ausgaben, um eine unvoreingenommene Verteilung zu erhalten.
Jeremiah Willcock

3

Ich empfehle die Boost.Random-Bibliothek , sie ist sehr detailliert und gut dokumentiert, lässt Sie explizit angeben, welche Verteilung Sie möchten, und kann in nicht kryptografischen Szenarien eine typische Rand-Implementierung der C-Bibliothek tatsächlich übertreffen .


1

Angenommen, min und max sind int-Werte. [und] bedeutet, diesen Wert einzuschließen. (und) bedeutet, diesen Wert nicht einzuschließen. Verwenden Sie oben, um mit c ++ rand () den richtigen Wert zu erhalten.

Referenz: für () [] definieren, besuchen:

https://en.wikipedia.org/wiki/Interval_(mathematics)

Informationen zur Rand- und Randfunktion oder zur Definition von RAND_MAX finden Sie unter:

http://en.cppreference.com/w/cpp/numeric/random/rand

[Minimal Maximal]

int randNum = rand() % (max - min + 1) + min

(Minimal Maximal]

int randNum = rand() % (max - min) + min + 1

[Minimal Maximal)

int randNum = rand() % (max - min) + min

(Minimal Maximal)

int randNum = rand() % (max - min - 1) + min + 1

0

In diesem Thread wurde die Stichprobenauswahl bereits besprochen, aber ich wollte eine Optimierung vorschlagen, die auf der Tatsache basiert, dass rand() % 2^somethingkeine Verzerrung eingeführt wird, wie oben bereits erwähnt.

Der Algorithmus ist wirklich einfach:

  • Berechnen Sie die kleinste Potenz von 2 größer als die Intervalllänge
  • randomisiere eine Zahl in diesem "neuen" Intervall
  • Geben Sie diese Zahl zurück, wenn sie kleiner als die Länge des ursprünglichen Intervalls ist
    • anderweitig ablehnen

Hier ist mein Beispielcode:

int randInInterval(int min, int max) {
    int intervalLen = max - min + 1;
    //now calculate the smallest power of 2 that is >= than `intervalLen`
    int ceilingPowerOf2 = pow(2, ceil(log2(intervalLen)));

    int randomNumber = rand() % ceilingPowerOf2; //this is "as uniform as rand()"

    if (randomNumber < intervalLen)
        return min + randomNumber;      //ok!
    return randInInterval(min, max);    //reject sample and try again
} 

Dies funktioniert besonders gut für kleine Intervalle, da die Potenz von 2 "näher" an der tatsächlichen Intervalllänge liegt und daher die Anzahl der Fehlschläge geringer ist.

PS
Natürlich wäre es effizienter, die Rekursion zu vermeiden (es ist nicht erforderlich, immer wieder über die Protokollobergrenze zu rechnen.), Aber ich dachte, dass dies für dieses Beispiel besser lesbar ist.


0

Beachten Sie, dass in den meisten Vorschlägen der anfängliche Zufallswert, den Sie von der Funktion rand () erhalten haben, der normalerweise von 0 bis RAND_MAX reicht, einfach verschwendet wird. Sie erstellen nur eine Zufallszahl daraus, während es eine solide Prozedur gibt, die Ihnen mehr geben kann.

Angenommen, Sie möchten einen [min, max] Bereich mit ganzzahligen Zufallszahlen. Wir beginnen bei [0, max-min]

Nehmen Sie die Basis b = max-min + 1

Beginnen Sie mit der Darstellung einer Zahl, die Sie von rand () in Basis b erhalten haben.

Auf diese Weise haben Sie Floor (log (b, RAND_MAX)), da jede Ziffer in Basis b, außer möglicherweise der letzten, eine Zufallszahl im Bereich [0, max-min] darstellt.

Natürlich ist die endgültige Verschiebung zu [min, max] für jede Zufallszahl r + min einfach.

int n = NUM_DIGIT-1;
while(n >= 0)
{
    r[n] = res % b;
    res -= r[n];
    res /= b;
    n--;
}

Wenn NUM_DIGIT die Anzahl der Ziffern in Basis b ist, die Sie extrahieren können, und das ist

NUM_DIGIT = floor(log(b,RAND_MAX))

dann ist das Obige eine einfache Implementierung des Extrahierens von NUM_DIGIT-Zufallszahlen von 0 bis b-1 aus einer RAND_MAX-Zufallszahl, die b <RAND_MAX liefert.


-1

Die Formel dafür ist sehr einfach. Probieren Sie diesen Ausdruck aus.

 int num = (int) rand() % (max - min) + min;  
 //Where rand() returns a random number between 0.0 and 1.0

2
Das ganze Problem bestand darin, den Rand von C / C ++ zu verwenden, der eine Ganzzahl in einem durch die Laufzeit angegebenen Bereich zurückgibt. Wie in diesem Thread gezeigt, ist die Zuordnung zufälliger Ganzzahlen von [0, RAND_MAX] zu [MIN, MAX] nicht ganz einfach, wenn Sie vermeiden möchten, ihre statistischen Eigenschaften oder ihre Leistung zu zerstören. Wenn Sie Doppelwerte im Bereich [0, 1] haben, ist die Zuordnung einfach.
Matěj Zábský

2
Ihre Antwort ist falsch, Sie sollten stattdessen Modul verwenden:int num = (int) rand() % (max - min) + min;
Jaime Ivan Cervantes

-2

Der folgende Ausdruck sollte unvoreingenommen sein, wenn ich mich nicht irre:

std::floor( ( max - min + 1.0 ) * rand() ) + min;

Ich gehe hier davon aus, dass rand () einen zufälligen Wert im Bereich zwischen 0,0 und 1,0 ohne 1,0 liefert und dass max und min ganze Zahlen mit der Bedingung sind, dass min <max.


std::floorgibt zurück double, und wir brauchen hier einen ganzzahligen Wert. Ich würde nur besetzen intanstatt zu verwenden std::floor.
Musiphil
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.