Gibt es eine Funktion zum Generieren einer zufälligen int-Zahl in C? Oder muss ich eine Drittanbieter-Bibliothek verwenden?
srand
: Warum nur einmal anrufen .
Gibt es eine Funktion zum Generieren einer zufälligen int-Zahl in C? Oder muss ich eine Drittanbieter-Bibliothek verwenden?
srand
: Warum nur einmal anrufen .
Antworten:
Hinweis : Nicht
rand()
aus Sicherheitsgründen verwenden. Wenn Sie eine kryptografisch sichere Nummer benötigen, lesen Sie stattdessen diese Antwort .
#include <time.h>
#include <stdlib.h>
srand(time(NULL)); // Initialization, should only be called once.
int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
Bearbeiten : Unter Linux bevorzugen Sie möglicherweise die Verwendung von Random und Srandom .
time()
Änderungen nur einmal pro Sekunde. Wenn Sie time()
für jeden Anruf an rand()
einen Startwert festlegen , erhalten Sie für jeden Anruf innerhalb einer Sekunde den gleichen Wert. Der größere Grund ist jedoch, dass die Eigenschaften rand()
und Funktionen wie diese am besten für den Anwendungsfall bekannt sind, bei dem sie genau einmal pro Lauf und nicht bei jedem einzelnen Aufruf gesetzt werden. Je nach "Zufälligkeit" mit ungetesteten oder unbewiesenen Eigenschaften kommt es zu Problemen.
rand()
normalerweise der Fall ist), mit dem Seeding rand()
im besten Fall überhaupt keine Wirkung hat und im schlimmsten Fall die bekannten Eigenschaften des Generators beeinträchtigt. Dies ist ein tiefes Thema. Beginnen Sie mit dem Lesen von Knuth Vol 2 Kapitel 3 über Zufallszahlen als beste Einführung in die Mathematik und die Fallstricke.
srand((unsigned int)time(NULL));
Die rand()
Funktion in <stdlib.h>
gibt eine pseudozufällige Ganzzahl zwischen 0 und zurück RAND_MAX
. Sie können srand(unsigned int seed)
einen Startwert festlegen.
Es ist üblich, den %
Operator in Verbindung mit rand()
zu verwenden, um einen anderen Bereich zu erhalten (bedenken Sie jedoch, dass dies die Gleichmäßigkeit etwas beeinträchtigt). Zum Beispiel:
/* random int between 0 and 19 */
int r = rand() % 20;
Wenn Ihnen die Einheitlichkeit wirklich am Herzen liegt, können Sie Folgendes tun:
/* Returns an integer in the range [0, n).
*
* Uses rand(), and so is affected-by/affects the same seed.
*/
int randint(int n) {
if ((n - 1) == RAND_MAX) {
return rand();
} else {
// Supporting larger values for n would requires an even more
// elaborate implementation that combines multiple calls to rand()
assert (n <= RAND_MAX)
// Chop off all of the values that would cause skew...
int end = RAND_MAX / n; // truncate skew
assert (end > 0);
end *= n;
// ... and ignore results from rand() that fall above that limit.
// (Worst case the loop condition should succeed 50% of the time,
// so we can expect to bail out of this loop pretty quickly.)
int r;
while ((r = rand()) >= end);
return r % n;
}
}
%
ist der Moduloperator . Es gibt Ihnen den Rest einer ganzzahligen Division, gibt Ihnen also x % n
immer eine Zahl zwischen 0
und n - 1
(solange x
und n
beide positiv sind). Wenn Sie das immer noch verwirrend finden, schreiben Sie ein Programm mit einer i
Anzahl von 0 bis 100 und drucken Sie es i % n
für einige n
Ihrer Auswahl aus, die kleiner als 100 sind.
Im Abschnitt zum sicheren Generieren von Zufallszahlen in verschiedenen Programmiersprachen sollten Sie einen der folgenden Schritte ausführen:
randombytes
API von libsodium/dev/urandom
nicht /dev/random
. Nicht OpenSSL (oder andere User-Space-PRNGs).Zum Beispiel:
#include "sodium.h"
int foo()
{
char myString[32];
uint32_t myInt;
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
return 1;
}
/* myString will be an array of 32 random bytes, not null-terminated */
randombytes_buf(myString, 32);
/* myInt will be a random number between 0 and 9 */
myInt = randombytes_uniform(10);
}
randombytes_uniform()
ist kryptografisch sicher und unvoreingenommen.
sodium_init()
irgendwann an. Mach dir keine Sorgen über das RNG, es verwendet den Kernel.
sodium_init()
obwohl dies nicht unbedingt Teil meines Beispiels ist, da es sich um ein wichtiges Detail handelt.
Lass uns das durchgehen. Zuerst verwenden wir die Funktion srand (), um den Randomizer zu setzen. Grundsätzlich kann der Computer Zufallszahlen basierend auf der Zahl generieren, die srand () zugeführt wird. Wenn Sie denselben Startwert angeben, werden jedes Mal dieselben Zufallszahlen generiert.
Daher müssen wir den Randomizer mit einem Wert setzen, der sich ständig ändert. Dazu geben wir den Wert der aktuellen Zeit mit der Funktion time () ein.
Wenn wir nun rand () aufrufen, wird jedes Mal eine neue Zufallszahl erzeugt.
#include <stdio.h>
int random_number(int min_num, int max_num);
int main(void)
{
printf("Min : 1 Max : 40 %d\n", random_number(1,40));
printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
return 0;
}
int random_number(int min_num, int max_num)
{
int result = 0, low_num = 0, hi_num = 0;
if (min_num < max_num)
{
low_num = min_num;
hi_num = max_num + 1; // include max_num in output
} else {
low_num = max_num + 1; // include max_num in output
hi_num = min_num;
}
srand(time(NULL));
result = (rand() % (hi_num - low_num)) + low_num;
return result;
}
else{ low_num=max_num; hi_num=min_num+1;
2) schlägt fehl wenn hi_num - low_num > INT_MAX
. 3) Lässt Werte in der seltenen Situation aus INT_MAX > hi_num - low_num > RAND_MAX
.
hi_num = max_num + 1;
Mangel an Überlaufschutz.
Wenn Sie Pseudozufallszahlen von besserer Qualität benötigen als diese stdlib
, schauen Sie sich Mersenne Twister an . Es ist auch schneller. Beispielimplementierungen sind beispielsweise hier reichlich vorhanden .
Die Standard-C-Funktion ist rand()
. Es ist gut genug, um Karten für Solitaire zu geben, aber es ist schrecklich. Viele Implementierungen von rand()
Zyklen durch eine kurze Liste von Zahlen, und die niedrigen Bits haben kürzere Zyklen. Die Art rand()
und Weise, wie manche Programme aufrufen, ist schrecklich, und es srand()
ist schwierig , einen guten Startwert zu berechnen .
Der beste Weg, um Zufallszahlen in C zu generieren, ist die Verwendung einer Drittanbieter-Bibliothek wie OpenSSL. Zum Beispiel,
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>
/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {
union {
unsigned int i;
unsigned char c[sizeof(unsigned int)];
} u;
do {
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
} while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */
return u.i % limit;
}
/* Random double in [0.0, 1.0) */
double random_double() {
union {
uint64_t i;
unsigned char c[sizeof(uint64_t)];
} u;
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
/* 53 bits / 2**53 */
return (u.i >> 11) * (1.0/9007199254740992.0);
}
int main() {
printf("Dice: %d\n", (int)(random_uint(6) + 1));
printf("Double: %f\n", random_double());
return 0;
}
Warum so viel Code? Andere Sprachen wie Java und Ruby haben Funktionen für zufällige Ganzzahlen oder Gleitkommazahlen. OpenSSL gibt nur zufällige Bytes an, daher versuche ich nachzuahmen, wie Java oder Ruby sie in Ganzzahlen oder Floats umwandeln würden.
Für ganze Zahlen wollen wir Modulo Bias vermeiden . Angenommen, wir haben zufällige 4-stellige Ganzzahlen erhalten rand() % 10000
, können aber rand()
nur 0 bis 32767 zurückgeben (wie in Microsoft Windows). Jede Zahl von 0 bis 2767 wird häufiger angezeigt als jede Zahl von 2768 bis 9999. Um die Abweichung zu beseitigen, können wir es erneut versuchen, rand()
während der Wert unter 2768 liegt, da die 30000-Werte von 2768 bis 32767 einheitlich auf die 10000-Werte von 0 bis abgebildet werden 9999.
Für Floats benötigen wir 53 zufällige Bits, da a eine double
Genauigkeit von 53 Bit enthält (vorausgesetzt, es handelt sich um ein IEEE-Double). Wenn wir mehr als 53 Bits verwenden, erhalten wir eine Rundungsvorspannung. Einige Programmierer schreiben Code wie rand() / (double)RAND_MAX
, geben jedoch rand()
möglicherweise nur 31 Bit oder nur 15 Bit in Windows zurück.
OpenSSLs RAND_bytes()
Samen selbst, vielleicht durch Lesen /dev/urandom
in Linux. Wenn wir viele Zufallszahlen benötigen, wäre es zu langsam, sie alle zu lesen /dev/urandom
, da sie aus dem Kernel kopiert werden müssen. Es ist schneller, OpenSSL zu erlauben, mehr Zufallszahlen aus einem Startwert zu generieren.
Mehr über Zufallszahlen:
srand()
. Es mischt Bits aus der aktuellen Zeit, der Prozess-ID und einigen Zeigern, wenn es nicht lesen kann /dev/urandom
.float
/ double
befasste. Daher habe ich die Frage geklärt, sich an int
Zahlen zu halten, um zu vermeiden, dass sie zu weit gefasst wird. Es gibt andere C-Fragen, die sich speziell mit float
/ double
zufälligen Werten befassen. Daher möchten Sie möglicherweise Ihre zweite Hälfte Ihrer Antwort auf Fragen wie stackoverflow.com/questions/13408990/…
Wenn Ihr System die arc4random
Funktionsfamilie unterstützt, würde ich empfehlen, diese anstelle der Standardfunktion zu rand
verwenden.
Die arc4random
Familie umfasst:
uint32_t arc4random(void)
void arc4random_buf(void *buf, size_t bytes)
uint32_t arc4random_uniform(uint32_t limit)
void arc4random_stir(void)
void arc4random_addrandom(unsigned char *dat, int datlen)
arc4random
Gibt eine zufällige vorzeichenlose 32-Bit-Ganzzahl zurück.
arc4random_buf
fügt zufälligen Inhalt in seinen Parameter ein buf : void *
. Die Menge des Inhalts wird durch den bytes : size_t
Parameter bestimmt.
arc4random_uniform
Gibt eine zufällige vorzeichenlose 32-Bit-Ganzzahl zurück, die der Regel folgt: 0 <= arc4random_uniform(limit) < limit
wobei limit auch eine vorzeichenlose 32-Bit-Ganzzahl ist.
arc4random_stir
liest Daten aus /dev/urandom
und übergibt die Daten an, arc4random_addrandom
um den internen Zufallszahlenpool zusätzlich zu randomisieren.
arc4random_addrandom
wird verwendet, um arc4random_stir
den internen Zufallszahlenpool entsprechend den an ihn übergebenen Daten zu füllen.
Wenn Sie diese Funktionen nicht haben, aber unter Unix arbeiten, können Sie diesen Code verwenden:
/* This is C, not C++ */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <stdio.h> /* printf */
int urandom_fd = -2;
void urandom_init() {
urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1) {
int errsv = urandom_fd;
printf("Error opening [/dev/urandom]: %i\n", errsv);
exit(1);
}
}
unsigned long urandom() {
unsigned long buf_impl;
unsigned long *buf = &buf_impl;
if (urandom_fd == -2) {
urandom_init();
}
/* Read 4 bytes, or 32 bits into *buf, which points to buf_impl */
read(urandom_fd, buf, sizeof(long));
return buf_impl;
}
Die urandom_init
Funktion öffnet das /dev/urandom
Gerät und fügt den Dateideskriptor ein urandom_fd
.
Die urandom
Funktion ist im Grunde die gleiche wie ein Aufruf von rand
, außer sicherer, und sie gibt a zurück long
(leicht änderbar).
Da /dev/urandom
dies jedoch etwas langsam sein kann, wird empfohlen, es als Startwert für einen anderen Zufallszahlengenerator zu verwenden.
Wenn Ihr System einen nicht haben /dev/urandom
, aber nicht eine hat /dev/random
oder ähnliche Datei, dann können Sie einfach den Pfad zu übergeben ändern open
in urandom_init
. Die in urandom_init
und urandom
meiner Meinung nach POSIX-kompatiblen Aufrufe und APIs sollten als solche auf den meisten, wenn nicht allen POSIX-kompatiblen Systemen funktionieren.
Hinweise: Ein Lesevorgang /dev/urandom
wird NICHT blockiert, wenn nicht genügend Entropie verfügbar ist. Daher können unter solchen Umständen generierte Werte kryptografisch unsicher sein. Wenn Sie sich darüber Sorgen machen, verwenden Sie diese Option /dev/random
, die bei unzureichender Entropie immer blockiert.
Wenn Sie sich auf einem anderen System (z. B. Windows) befinden, verwenden Sie rand
oder eine interne Windows-spezifische plattformabhängige nicht portierbare API.
Wrapper - Funktion für urandom
, rand
oder arc4random
Anrufe:
#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
int myRandom(int bottom, int top){
return (RAND_IMPL() % (top - bottom)) + bottom;
}
STL existiert nicht für C. Sie müssen anrufen rand
oder noch besser random
. Diese werden im Standardbibliotheksheader deklariert stdlib.h
. rand
ist POSIX, random
ist eine BSD-Spezifikationsfunktion.
Der Unterschied zwischen rand
und random
besteht darin, dass random
eine viel besser verwendbare 32-Bit-Zufallszahl und rand
normalerweise eine 16-Bit-Zahl zurückgegeben wird. Die BSD-Manpages zeigen, dass die unteren Bits von rand
zyklisch und vorhersehbar sind und daher rand
für kleine Zahlen möglicherweise unbrauchbar sind.
extern int rand(void);
und extern void srand(unsigned int);
.
Schauen Sie sich ISAAC an (Indirektion, Verschiebung, Akkumulieren, Hinzufügen und Zählen). Es ist gleichmäßig verteilt und hat eine durchschnittliche Zykluslänge von 2 ^ 8295.
Dies ist ein guter Weg, um eine Zufallszahl zwischen zwei Zahlen Ihrer Wahl zu erhalten.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define randnum(min, max) \
((rand() % (int)(((max) + 1) - (min))) + (min))
int main()
{
srand(time(NULL));
printf("%d\n", randnum(1, 70));
}
Erstmalige Ausgabe: 39
Beim zweiten Mal ausgeben: 61
Zum dritten Mal ausgeben: 65
Sie können die Werte danach randnum
in beliebige Zahlen ändern , und es wird eine Zufallszahl zwischen diesen beiden Zahlen für Sie generiert.
Sie möchten verwenden rand()
. Hinweis ( SEHR WICHTIG ): Stellen Sie sicher, dass Sie den Startwert für die Rand-Funktion festlegen. Wenn Sie dies nicht tun, sind Ihre Zufallszahlen nicht wirklich zufällig . Das ist sehr, sehr, sehr wichtig. Zum Glück können Sie normalerweise eine Kombination aus dem System-Ticks-Timer und dem Datum verwenden, um einen guten Startwert zu erhalten.
FWIW, die Antwort lautet: Ja, es gibt eine stdlib.h
Funktion namens rand
; Diese Funktion ist in erster Linie auf Geschwindigkeit und Verteilung abgestimmt, nicht auf Unvorhersehbarkeit. Fast alle integrierten Zufallsfunktionen für verschiedene Sprachen und Frameworks verwenden diese Funktion standardmäßig. Es gibt auch "kryptografische" Zufallszahlengeneratoren, die viel weniger vorhersehbar sind, aber viel langsamer laufen. Diese sollten in jeder sicherheitsrelevanten Anwendung verwendet werden.
Dies ist hoffentlich etwas zufälliger als nur zu verwenden srand(time(NULL))
.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
srand((unsigned int)**main + (unsigned int)&argc + (unsigned int)time(NULL));
srand(rand());
for (int i = 0; i < 10; i++)
printf("%d\n", rand());
}
Nun, STL ist C ++, nicht C, also weiß ich nicht, was Sie wollen. Wenn Sie jedoch C möchten, gibt es die rand()
und srand()
-Funktionen:
int rand(void);
void srand(unsigned seed);
Diese sind beide Teil von ANSI C. Es gibt auch die random()
Funktion:
long random(void);
Aber soweit ich das beurteilen kann, random()
handelt es sich nicht um Standard-ANSI C. Eine Bibliothek von Drittanbietern ist möglicherweise keine schlechte Idee, aber alles hängt davon ab, wie zufällig eine Zahl ist, die Sie wirklich generieren müssen.
C Programm zur Erzeugung einer Zufallszahl zwischen 9 und 50
#include <time.h>
#include <stdlib.h>
int main()
{
srand(time(NULL));
int lowerLimit = 10, upperLimit = 50;
int r = lowerLimit + rand() % (upperLimit - lowerLimit);
printf("%d", r);
}
Im Allgemeinen können wir eine Zufallszahl zwischen LowerLimit und UpperLimit-1 generieren
dh LowerLimit ist inklusive oder sagt r ∈ [LowerLimit, UpperLimit)
rand()
ist der bequemste Weg, um Zufallszahlen zu generieren.
Sie können auch Zufallszahlen von jedem Onlinedienst wie random.org abrufen.
#include <stdio.h>
#include <stdlib.h>
void main()
{
int visited[100];
int randValue, a, b, vindex = 0;
randValue = (rand() % 100) + 1;
while (vindex < 100) {
for (b = 0; b < vindex; b++) {
if (visited[b] == randValue) {
randValue = (rand() % 100) + 1;
b = 0;
}
}
visited[vindex++] = randValue;
}
for (a = 0; a < 100; a++)
printf("%d ", visited[a]);
}
#include <stdio.h>
#include <dos.h>
int random(int range);
int main(void)
{
printf("%d", random(10));
return 0;
}
int random(int range)
{
struct time t;
int r;
gettime(&t);
r = t.ti_sec % range;
return r;
}
Auf modernen x86_64-CPUs können Sie den Hardware-Zufallszahlengenerator über verwenden _rdrand64_step()
Beispielcode:
#include <immintrin.h>
uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
// Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//generate number in range [min,max)
int random(int min, int max){
int number = min + rand() % (max - min);
return number;
}
//Driver code
int main(){
srand(time(NULL));
for(int i = 1; i <= 10; i++){
printf("%d\t", random(10, 100));
}
return 0;
}
Als rand()
ich eine gute Erklärung hörte, warum es eine schlechte Idee ist, gleichmäßig verteilte Zufallszahlen in einem bestimmten Bereich zu erzeugen, beschloss ich, einen Blick darauf zu werfen, wie verzerrt die Ausgabe tatsächlich ist. Mein Testfall war faires Würfeln. Hier ist der C-Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
int i;
int dice[6];
for (i = 0; i < 6; i++)
dice[i] = 0;
srand(time(NULL));
const int TOTAL = 10000000;
for (i = 0; i < TOTAL; i++)
dice[(rand() % 6)] += 1;
double pers = 0.0, tpers = 0.0;
for (i = 0; i < 6; i++) {
pers = (dice[i] * 100.0) / TOTAL;
printf("\t%1d %5.2f%%\n", dice[i], pers);
tpers += pers;
}
printf("\ttotal: %6.2f%%\n", tpers);
}
und hier ist seine Ausgabe:
$ gcc -o t3 t3.c
$ ./t3
1666598 16.67%
1668630 16.69%
1667682 16.68%
1666049 16.66%
1665948 16.66%
1665093 16.65%
total: 100.00%
$ ./t3
1667634 16.68%
1665914 16.66%
1665542 16.66%
1667828 16.68%
1663649 16.64%
1669433 16.69%
total: 100.00%
Ich weiß nicht, wie einheitlich Ihre Zufallszahlen sein müssen, aber das Obige scheint für die meisten Anforderungen einheitlich genug zu sein.
Bearbeiten: Es wäre eine gute Idee, das PRNG mit etwas Besserem als zu initialisieren time(NULL)
.
Ich hatte in meiner letzten Anwendung ein ernstes Problem mit dem Pseudozufallszahlengenerator: Ich habe mein C-Programm wiederholt über ein Pyhton-Skript aufgerufen und den folgenden Code als Startwert verwendet:
srand(time(NULL))
Da jedoch:
man srand
);time
wird wird jedes Mal derselbe Wert zurückgegeben.Mein Programm hat die gleiche Zahlenfolge generiert. Sie können drei Dinge tun, um dieses Problem zu lösen:
Mischzeitausgabe mit einigen anderen Informationen, die sich bei Läufen ändern (in meiner Anwendung der Ausgabename):
srand(time(NULL) | getHashOfString(outputName))
Ich habe djb2 als Hash-Funktion verwendet.
Erhöhen Sie die Zeitauflösung. Auf meiner Plattform clock_gettime
war verfügbar, also benutze ich es:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec);
Verwenden Sie beide Methoden zusammen:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec | getHashOfString(outputName));
Option 3 stellt sicher, dass Sie (soweit ich weiß) die beste Zufalls-Zufälligkeit haben, kann jedoch nur bei sehr schneller Anwendung einen Unterschied bewirken. Meiner Meinung nach ist Option 2 eine sichere Wette.
rand()
sollte nicht für kryptografische Daten verwendet werden, stimme ich zu. Zumindest für mich enthielt meine Anwendung keine kryptografischen Daten, daher war die angegebene Methode für mich in Ordnung.
Trotz aller Vorschläge der Leute rand()
hier möchten Sie nicht verwenden, es rand()
sei denn, Sie müssen! Die Zufallszahlen, dierand()
erzeugt werden sind oft sehr schlecht. Um aus der Linux-Manpage zu zitieren:
Die Versionen von
rand()
undsrand()
in der Linux C-Bibliothek verwenden denselben Zufallszahlengenerator wierandom(3)
undsrandom(3)
, daher sollten die Bits niedrigerer Ordnung genauso zufällig sein wie die Bits höherer Ordnung. Bei älteren rand () - Implementierungen und bei aktuellen Implementierungen auf verschiedenen Systemen sind die Bits niedrigerer Ordnung jedoch viel weniger zufällig als die Bits höherer Ordnung . Verwenden Sie diese Funktion nicht in Anwendungen, die portabel sein sollen, wenn eine gute Zufälligkeit erforderlich ist. ( Verwenden Sierandom(3)
stattdessen. )
In Bezug auf die Portabilität random()
wird dies seit geraumer Zeit auch vom POSIX-Standard definiert. rand()
älter ist, erschien es bereits in der ersten POSIX.1-Spezifikation (IEEE Std 1003.1-1988), wohingegenrandom()
zuerst in POSIX.1-2001 (IEEE Std 1003.1-2001) erschien, der aktuelle POSIX-Standard ist jedoch bereits POSIX.1-2008 (IEEE Std 1003.1-2008), die vor einem Jahr ein Update erhalten hat (IEEE Std 1003.1-2008, Ausgabe 2016). Daher würde ich es als random()
sehr tragbar betrachten.
POSIX.1-2001 führte auch die Funktionen lrand48()
und ein mrand48()
, siehe hier :
Diese Funktionsfamilie soll Pseudozufallszahlen unter Verwendung eines linearen Kongruenzalgorithmus und einer 48-Bit-Ganzzahlarithmetik erzeugen.
Und eine ziemlich gute Pseudozufallsquelle ist die arc4random()
Funktion, die auf vielen Systemen verfügbar ist. Nicht Teil eines offiziellen Standards, erschien um 1997 in BSD, aber Sie können ihn auf Systemen wie Linux und macOS / iOS finden.
random()
existiert unter Windows nicht.
rand()
da dies auch vom C-Standard verlangt wird. Für alles andere benötigen Sie wie gewohnt nur eine spezielle Lösung für Windows. #ifdef _WIN32
ist der Ausdruck, den Sie am häufigsten in plattformübergreifendem Code sehen, der Windows unterstützen möchte. In der Regel gibt es eine Lösung, die mit allen Systemen funktioniert, und eine, die nur für Windows erforderlich ist.
Für Linux C-Anwendungen:
Dies ist mein überarbeiteter Code aus einer Antwort oben, die meinen C-Code-Praktiken folgt und einen zufälligen Puffer beliebiger Größe (mit geeigneten Rückkehrcodes usw.) zurückgibt. Stellen Sie sicher, dass Sie zu urandom_open()
Beginn Ihres Programms einmal aufrufen .
int gUrandomFd = -1;
int urandom_open(void)
{
if (gUrandomFd == -1) {
gUrandomFd = open("/dev/urandom", O_RDONLY);
}
if (gUrandomFd == -1) {
fprintf(stderr, "Error opening /dev/urandom: errno [%d], strerrer [%s]\n",
errno, strerror(errno));
return -1;
} else {
return 0;
}
}
void urandom_close(void)
{
close(gUrandomFd);
gUrandomFd = -1;
}
//
// This link essentially validates the merits of /dev/urandom:
// http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
//
int getRandomBuffer(uint8_t *buf, int size)
{
int ret = 0; // Return value
if (gUrandomFd == -1) {
fprintf(stderr, "Urandom (/dev/urandom) file not open\n");
return -1;
}
ret = read(gUrandomFd, buf, size);
if (ret != size) {
fprintf(stderr, "Only read [%d] bytes, expected [%d]\n",
ret, size);
return -1;
} else {
return 0;
}
}
Meine minimalistische Lösung sollte für Zufallszahlen im Bereich funktionieren [min, max)
. Verwenden Sie diese srand(time(NULL))
Option, bevor Sie die Funktion aufrufen.
int range_rand(int min_num, int max_num) {
if (min_num >= max_num) {
fprintf(stderr, "min_num is greater or equal than max_num!\n");
}
return min_num + (rand() % (max_num - min_num));
}
Versuchen Sie dies, ich habe es aus einigen der Konzepte zusammengestellt, auf die oben bereits verwiesen wurde:
/*
Uses the srand() function to seed the random number generator based on time value,
then returns an integer in the range 1 to max. Call this with random(n) where n is an integer, and you get an integer as a return value.
*/
int random(int max) {
srand((unsigned) time(NULL));
return (rand() % max) + 1;
}
srand()
jedes Mal anzurufen, wenn Sie anrufen möchten rand()
. Da time()
normalerweise ein Wert in Sekunden zurückgegeben wird , gibt das schnelle Aufrufen dieser Funktion denselben "zufälligen" Wert zurück.
random()
Funktion verwechselt .