C rasgele bir int numarası üretmek için bir işlevi var mı? Yoksa üçüncü taraf bir kütüphane mi kullanmam gerekecek?
srand
: neden sadece bir kez çağırın .
C rasgele bir int numarası üretmek için bir işlevi var mı? Yoksa üçüncü taraf bir kütüphane mi kullanmam gerekecek?
srand
: neden sadece bir kez çağırın .
Yanıtlar:
Not :
rand()
Güvenlik için kullanmayın . Kriptografik olarak güvenli bir numaraya ihtiyacınız varsa, bunun yerine bu cevaba bakın .
#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.
Düzenleme : Linux'ta rasgele ve srandom kullanmayı tercih edebilirsiniz .
time()
Saniyede yalnızca bir kez değişir. Şuradan ayrılırsanız time()
, her çağrı için rand()
tek bir saniye boyunca her çağrı için aynı değeri alırsınız. Ancak en büyük neden, rand()
her bir çağrıda değil, her çalışmada tam olarak bir kez tohumlandıkları kullanım durumu için özelliklerinin ve işlevlerinin en iyi bilinmesidir. Test edilmemiş veya kanıtlanmamış özelliklere sahip "rastgelelik" e bağlı olarak soruna yol açar.
rand()
genellikle budur) tohumlamanın rand()
en iyi şekilde hiçbir etkisi olmaz ve en kötü ihtimalle jeneratörün bilinen özelliklerini bozar. Bu derin bir konu. Matematik ve tuzaklara en iyi giriş olarak rastgele sayılar üzerinde Knuth Cilt 2 Bölüm 3'ü okumaya başlayın .
srand((unsigned int)time(NULL));
İçindeki rand()
işlev <stdlib.h>
0 ile arasında bir rasgele rasgele tamsayı döndürür RAND_MAX
. Kullanabilirsinizsrand(unsigned int seed)
Bir tohum ayarlamak için .
Farklı bir menzil elde etmek için %
operatörü birlikte kullanmak yaygın bir uygulamadır rand()
(bunun tekdüzeliği bir şekilde attığını unutmayın). Örneğin:
/* random int between 0 and 19 */
int r = rand() % 20;
Eğer varsa gerçekten bütünlüğü umurumda böyle bir şey yapabilirsiniz:
/* 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;
}
}
%
Modül operatörüdür. Size bir tamsayı bölümünün geri kalanını verir, bu yüzden x % n
her zaman 0
ve arasında bir sayı verecektir n - 1
( x
ve n
her ikisi de pozitif olduğu sürece ). Hala kafa karıştırıcı olduğunu fark ederseniz, bir programı yazmayı deneyin i
0 ile 100 sayar, baskılar i % n
bazıları için n
senin seçmenin daha küçük 100.
Çeşitli programlama dillerinde rasgele sayıların nasıl güvenli bir şekilde oluşturulacağı konusunda ele alındığı gibi , aşağıdakilerden birini yapmak istersiniz:
randombytes
API/dev/urandom
değil /dev/random
. OpenSSL (veya diğer kullanıcı alanı PRNG'leri) değil.Örneğin:
#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()
kriptografik olarak güvenli ve tarafsızdır.
sodium_init()
. RNG için endişelenmeyin, çekirdeği kullanır.
sodium_init()
Önemli bir ayrıntı olduğu için örneğimin bir parçası olmamasına rağmen son düzenlemeyi onayladım .
Hadi bunun üzerinden geçelim. İlk önce rasgeleleştiriciyi tohumlamak için srand () işlevini kullanıyoruz. Temel olarak, bilgisayar srand () öğesine beslenen sayıya göre rastgele sayılar üretebilir. Aynı tohum değerini verdiyseniz, her seferinde aynı rastgele sayılar üretilir.
Bu nedenle, randomizörü her zaman değişen bir değerle tohumlamalıyız. Bunu, time () işleviyle geçerli zamanın değerini besleyerek yaparız.
Şimdi, rand () dediğimizde, her seferinde yeni bir rastgele sayı üretilecektir.
#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) ne zaman başarısız olur hi_num - low_num > INT_MAX
. 3) Nadir durumlarda değerleri atlar INT_MAX > hi_num - low_num > RAND_MAX
.
hi_num = max_num + 1;
taşmaya karşı korumadan yoksundur.
Sağlananlardan daha kaliteli sahte rasgele sayılara ihtiyacınız varsa stdlib
, Mersenne Twister'a göz atın . Aynı zamanda daha hızlı. Örnek uygulamalar çok fazla, örneğin burada .
Standart C işlevi rand()
. Solitaire için kart dağıtmak için yeterince iyi, ama korkunç. Birçok uygulama, rand()
kısa bir sayı listesinden geçer ve düşük bitler daha kısa döngülere sahiptir. Bazı programların çağırma rand()
şekli korkunçtur ve geçmesi için iyi bir tohum hesaplamak srand()
zordur.
C'de rastgele sayılar üretmenin en iyi yolu OpenSSL gibi üçüncü taraf bir kitaplık kullanmaktır. Örneğin,
#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;
}
Neden bu kadar kod? Java ve Ruby gibi diğer dillerde rasgele tamsayılar veya kayan noktalar için işlevler bulunur. OpenSSL yalnızca rastgele bayt verir, bu yüzden Java veya Ruby'nin bunları tamsayılara veya kayan noktalara nasıl dönüştüreceğini taklit etmeye çalışırım.
Tamsayılar için, modulo yanlılığından kaçınmak istiyoruz . Diyelim ki bazı rastgele 4 basamaklı tamsayılarımız var rand() % 10000
, ancak rand()
yalnızca 0 - 32767 (Microsoft Windows'da olduğu gibi) döndürebilir. 0'dan 2767'ye kadar olan her sayı 2768'den 9999'a kadar her sayıdan daha sık görünecektir. Yanlılığı kaldırmak için rand()
, değer 2768'in altındayken tekrar deneyebiliriz , çünkü 2768'den 32767'ye kadar 30000 değerleri 0'dan 10000'e eşleştirilir. 9999.
Şamandıralar için 53 rastgele bit istiyoruz, çünkü double
53 bitlik hassasiyet (IEEE çift olduğu varsayılarak) var. 53 bitten fazla kullanırsak, yuvarlama sapması elde ederiz. Bazı programcılar gibi kod yazmak rand() / (double)RAND_MAX
, ancak rand()
Windows'da yalnızca 31 bit veya yalnızca 15 bit döndürebilir.
OpenSSL'nin RAND_bytes()
tohumları, belki de /dev/urandom
Linux'ta okuyarak . Çok sayıda rastgele sayıya ihtiyacımız varsa, hepsini okumak çok yavaş olurdu /dev/urandom
, çünkü çekirdekten kopyalanmaları gerekir. OpenSSL'nin bir tohumdan daha fazla rasgele sayı üretmesine izin vermek daha hızlıdır.
Rasgele sayılar hakkında daha fazla bilgi:
srand()
. Geçerli saatten, işlem kimliğinden ve bazı işaretçileri okuyamazsa karıştırır /dev/urandom
.float
/ ile başa çıkmak için ekstra bir yorum yapan tek kişi sizsiniz double
, bu yüzden soruyu çok genişlememek için int
sayılara sadık kalmak için açıkladım . Özellikle float
/ double
rastgele değerlerle ilgili başka C soruları da var , bu nedenle stackoverflow.com/questions/13408990/…
Sisteminiz arc4random
işlev ailesini destekliyorsa, bunun yerine standart rand
işlevi kullanmanızı öneririm .
arc4random
Aile içerir:
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
rastgele bir 32 bit işaretsiz tam sayı döndürür.
arc4random_buf
parametresine rastgele içerik koyar buf : void *
. İçerik miktarı bytes : size_t
parametre tarafından belirlenir .
arc4random_uniform
kuralı izleyen rastgele bir 32 bit işaretsiz tam sayı döndürür: 0 <= arc4random_uniform(limit) < limit
burada sınır aynı zamanda işaretsiz bir 32 bit tam sayıdır.
arc4random_stir
dahili rasgele sayı havuzuna ek olarak rasgele eklenmek /dev/urandom
üzere verileri okur ve bu veriye arc4random_addrandom
aktarır.
arc4random_addrandom
tarafından arc4random_stir
aktarılan verilere göre dahili rasgele sayı havuzunu doldurmak için kullanılır .
Bu işlevlere sahip değilseniz, ancak Unix'deyseniz, bu kodu kullanabilirsiniz:
/* 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;
}
urandom_init
Fonksiyon açar /dev/urandom
cihazı ve dosya tanımlayıcısı koyar urandom_fd
.
urandom
Fonksiyon temelde bir çağrı aynıdır rand
daha güvenli hariç ve bir döner long
(kolayca değiştirilebilir).
Bununla birlikte, /dev/urandom
biraz yavaş olabilir, bu yüzden farklı bir rastgele sayı üreteci için bir tohum olarak kullanmanız önerilir.
Sisteminiz bir yoksa /dev/urandom
, ama yok bir var /dev/random
ya da benzeri bir dosya, o zaman sadece geçirilen yolunu değiştirebilir open
içinde urandom_init
. POSIX uyumlu urandom_init
ve kullanılan aramalar ve API'lar urandom
, POSIX uyumlu sistemlerin hepsinde olmasa bile çoğunda çalışmalıdır.
Notlar: /dev/urandom
Yeterli entropi yoksa okuma değeri engellenmez, bu nedenle bu koşullar altında üretilen değerler kriptografik olarak güvensiz olabilir. Bu konuda endişeleriniz varsa, o zaman kullanın /dev/random
, yetersiz entropi varsa her zaman engellenir.
Başka bir sistemdeyseniz (örn. Windows), rand
Windows'a özgü platforma özgü taşınabilir olmayan bir API kullanın.
Fonksiyon için Sarıcı urandom
, rand
ya arc4random
aramalar:
#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
int myRandom(int bottom, int top){
return (RAND_IMPL() % (top - bottom)) + bottom;
}
C için STL mevcut değil. Aramanız rand
veya daha iyisi random
. Bunlar standart kütüphane başlığında bildirilmiştir stdlib.h
. rand
POSIX, random
bir BSD spesifikasyon fonksiyonudur.
Arasındaki fark rand
ve random
olmasıdır random
çok daha kullanışlı bir 32-bit rasgele sayı döner ve rand
tipik olarak 16 bit sayısını verir. BSD manajları, düşük bitlerin rand
döngüsel ve öngörülebilir olduğunu gösterir, bu nedenle rand
küçük sayılar için potansiyel olarak işe yaramaz.
extern int rand(void);
ve var extern void srand(unsigned int);
.
ISAAC'a (Dolaylı, Shift, Biriktir, Ekle ve Say) göz atın . Eşit dağılmış ve ortalama döngü uzunluğu 2 ^ 8295'tir.
Bu, seçtiğiniz iki sayı arasında rastgele bir sayı almanın iyi bir yoludur.
#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));
}
İlk çıkış: 39
İkinci kez çıktı: 61
Üçüncü kez çıktı: 65
Sonraki değerleri randnum
seçtiğiniz sayılara göre değiştirebilirsiniz ve bu iki sayı arasında sizin için rastgele bir sayı oluşturur.
Kullanmak istiyorsun rand()
. Not ( ÇOK ÖNEMLİ ): rand işlevi için tohumu ayarladığınızdan emin olun. Bunu yapmazsanız, rastgele sayılarınız gerçekten rastgele değildir . Bu çok, çok, çok önemli. Neyse ki, genellikle iyi bir tohum almak için sistem keneler zamanlayıcı ve tarihin bir kombinasyonunu kullanabilirsiniz.
FWIW, cevap şu ki, evet, stdlib.h
denilen bir fonksiyon var rand
; bu işlev, öngörülemezlik için değil, öncelikli olarak hız ve dağıtım için ayarlanır. Çeşitli diller ve çerçeveler için neredeyse tüm yerleşik rastgele işlevler varsayılan olarak bu işlevi kullanır. Daha az tahmin edilebilir, ancak çok daha yavaş çalışan "kriptografik" rastgele sayı üreteçleri de vardır. Bunlar güvenlikle ilgili her türlü uygulamada kullanılmalıdır.
Umarım sadece kullanmaktan biraz daha rastgeledir 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());
}
STL C ++, C değil, bu yüzden ne istediğini bilmiyorum. Bununla birlikte, C'yi istiyorsanız, rand()
ve srand()
işlevleri vardır:
int rand(void);
void srand(unsigned seed);
Bunlar, aynı zamanda var olan ANSI C'ye her iki parçası random()
işlevi:
long random(void);
Ancak anlayabildiğim kadarıyla random()
standart ANSI C değil. Üçüncü taraf bir kütüphane kötü bir fikir olmayabilir, ancak hepsi gerçekten bir sayının ne kadar rastgele üretmeniz gerektiğine bağlıdır.
C 9 ile 50 arasında rastgele sayı üretecek program
#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);
}
Genel olarak lowerLimit ve upperLimit-1 arasında rastgele bir sayı üretebiliriz
Yani lowerLimit kapsayıcıdır veya r ∈ [lowerLimit, upperLimit) deyin
rand()
rastgele sayılar üretmenin en uygun yoludur.
Ayrıca random.org gibi herhangi bir çevrimiçi hizmetten rastgele sayı yakalayabilirsiniz.
#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;
}
Modern x86_64 işlemcilerinde donanım rasgele sayı üretecini _rdrand64_step()
Örnek kod:
#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;
}
rand()
Belirli bir aralıkta düzgün dağılmış rasgele sayılar üretmek için kullanmanın kötü bir fikir olduğunu iyi bir şekilde duyduğumda, çıktının gerçekte ne kadar çarpık olduğuna bir göz atmaya karar verdim. Test durumum adil zar atmaktı. İşte C kodu:
#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);
}
ve işte çıktısı:
$ 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%
Rastgele sayılarınızın ne kadar üniform olması gerektiğini bilmiyorum, ancak yukarıdakiler çoğu ihtiyaç için yeterince üniform görünüyor.
Düzenleme: PRNG daha iyi bir şey ile başlatmak için iyi bir fikir olacaktır time(NULL)
.
Son uygulamada sözde rasgele sayı üreteci ile ciddi bir sorun vardı: tekrar tekrar bir pyhton komut dosyası aracılığıyla C programımı çağırdı ve tohum olarak aşağıdaki kodu kullanıyordum:
srand(time(NULL))
Ancak, şu tarihten beri:
man srand
);time
her seferinde aynı değeri döndürür.Programım aynı sayı dizisini üretti. Bu sorunu çözmek için 3 şey yapabilirsiniz:
çalışır durumda değişen diğer bazı bilgiler ile zaman çıktısını karıştır (benim uygulama, çıktı adı):
srand(time(NULL) | getHashOfString(outputName))
Hash fonksiyonum olarak djb2 kullandım .
Zaman çözünürlüğünü artırın. Platformumda clock_gettime
mevcuttu, bu yüzden kullanıyorum:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec);
Her iki yöntemi birlikte kullanın:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec | getHashOfString(outputName));
Seçenek 3 (bildiğim kadarıyla) en iyi tohum rasgeleliğini sağlar, ancak sadece çok hızlı uygulamada bir fark yaratabilir. Bence seçenek 2 güvenli bir bahis.
rand()
kriptografik veriler için kullanılmamalıdır, katılıyorum. En azından benim için, uygulamam şifreleme verisi içermiyordu, bu yüzden benim için verilen yöntem iyiydi.
rand()
Burada tüm insanların önerilerine rağmen , rand()
gerekmedikçe kullanmak istemezsiniz ! Üreten rastgele sayılar rand()
genellikle çok kötüdür. Linux kılavuz sayfasından alıntı yapmak için:
Versiyonları
rand()
vesrand()
Linux C Kütüphanesi ile aynı üretici kullanılmaktadırrandom(3)
vesrandom(3)
düşük bitler daha yüksek bitleri gibi rasgele gibi olmalıdır, böylece. Bununla birlikte, daha eski rand () uygulamalarında ve farklı sistemlerde mevcut uygulamalarda , düşük dereceli bitler yüksek dereceli bitlerden çok daha az rastgeledir . İyi rasgelelik gerektiğinde taşınabilir olması amaçlanan uygulamalarda bu işlevi kullanmayın. ( Bunun yerine kullanınrandom(3)
. )
Taşınabilirlik ile ilgili olarak random()
, POSIX standardı tarafından bir süredir tanımlanmaktadır. rand()
daha eski, ilk POSIX.1 spesifikasyonunda (IEEE Std 1003.1-1988) random()
ortaya çıktı , ilk olarak POSIX.1-2001'de (IEEE Std 1003.1-2001) ortaya çıktı, ancak mevcut POSIX standardı zaten POSIX.1-2008 (IEEE Std 1003.1-2008), sadece bir yıl önce bir güncelleme aldı (IEEE Std 1003.1-2008, 2016 Sürümü). Bu yüzden random()
çok taşınabilir olmayı düşünürdüm .
POSIX.1-2001 lrand48()
ve mrand48()
işlevlerini de tanıttı, buraya bakın :
Bu işlev ailesi, doğrusal bir eş algoritma ve 48 bit tam sayı aritmetiği kullanılarak sözde rasgele sayılar üretecektir.
Ve oldukça iyi sözde rastgele kaynak arc4random()
birçok sistemde bulunan işlevdir. Herhangi bir resmi standardın parçası değil, 1997'de BSD'de ortaya çıktı, ancak Linux ve macOS / iOS gibi sistemlerde bulabilirsiniz.
random()
Windows'ta mevcut değil.
rand()
C standardı için gerekli olduğu için destekliyor . Her şey için, her zamanki gibi sadece Windows için özel bir çözüme ihtiyacınız var. #ifdef _WIN32
en çok Windows'u desteklemek isteyen platformlar arası kodda göreceğiniz ve genellikle tüm sistemlerle çalışan ve yalnızca Windows için gerekli olan bir çözüm var.
Linux C uygulamaları için:
Bu benim C kodu uygulamaları takip ve herhangi bir boyutta (uygun dönüş kodları, vb ile) rastgele bir tampon döndürür yukarıdaki bir cevap yeniden işlenmiş kodu. urandom_open()
Programınızın başında bir kez aradığınızdan emin olun .
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;
}
}
Minimalist çözümüm aralıktaki rastgele sayılar için çalışmalıdır [min, max)
. srand(time(NULL))
İşlevi çağırmadan önce kullanın .
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));
}
Bunu deneyin, yukarıda yukarıda belirtilen bazı kavramlardan bir araya getirdim:
/*
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()
çağrıya istediğiniz her zaman rand()
çok kötü bir fikir. Beri time()
tipik bir değer döndürür saniye aynı "rasgele" değeri döndürecektir hızla bu işlevi çağırarak.
random()
işleviyle karıştırılır .