Apakah ada fungsi untuk menghasilkan bilangan int acak dalam C? Atau apakah saya harus menggunakan perpustakaan pihak ketiga?
srand
: mengapa menyebutnya hanya sekali .
Apakah ada fungsi untuk menghasilkan bilangan int acak dalam C? Atau apakah saya harus menggunakan perpustakaan pihak ketiga?
srand
: mengapa menyebutnya hanya sekali .
Jawaban:
Catatan : Jangan gunakan
rand()
untuk keamanan. Jika Anda memerlukan nomor yang aman secara kriptografis, lihat jawaban ini sebagai gantinya.
#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.
Sunting : Di Linux, Anda mungkin lebih suka menggunakan acak dan acak .
time()
hanya berubah sekali per detik. Jika Anda memotong dari time()
, untuk setiap panggilan rand()
, maka Anda akan mendapatkan nilai yang sama untuk setiap panggilan selama satu detik. Tetapi alasan yang lebih besar adalah bahwa properti rand()
dan fungsi seperti itu dikenal terbaik untuk use case di mana mereka diunggulkan tepat sekali per run, dan tidak pada setiap panggilan tunggal. Bergantung pada "keacakan" dengan properti yang belum diuji atau tidak terbukti menyebabkan masalah.
rand()
biasanya adalah) penyemaian dengan cara rand()
terbaik tidak akan berpengaruh sama sekali, dan paling buruk akan merusak kualitas generator yang diketahui. Ini adalah subjek yang mendalam. Mulailah dengan membaca Knuth Vol 2 Bab 3 pada angka acak sebagai pengantar terbaik untuk matematika dan perangkap.
srand((unsigned int)time(NULL));
The rand()
fungsi dalam <stdlib.h>
pengembalian integer pseudo-acak antara 0 dan RAND_MAX
. Anda bisa menggunakan srand(unsigned int seed)
untuk mengatur seed.
Ini adalah praktik umum untuk menggunakan %
operator bersamaan rand()
untuk mendapatkan rentang yang berbeda (meskipun perlu diingat bahwa ini agak menghilangkan keseragaman). Sebagai contoh:
/* random int between 0 and 19 */
int r = rand() % 20;
Jika Anda benar-benar peduli tentang keseragaman, Anda dapat melakukan sesuatu seperti ini:
/* 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;
}
}
%
Adalah operator modulus. Ini memberi Anda sisa dari divisi integer, jadi x % n
akan selalu memberi Anda nomor di antara 0
dan n - 1
(selama x
dan n
keduanya positif). Jika Anda masih merasa itu membingungkan, cobalah menulis sebuah program yang memiliki i
hitungan dari 0 hingga 100, dan cetak i % n
untuk beberapa n
pilihan Anda yang lebih kecil dari 100.
Sebagaimana dibahas dalam cara menghasilkan angka acak dengan aman dalam berbagai bahasa pemrograman , Anda harus melakukan salah satu dari yang berikut:
randombytes
API/dev/urandom
, bukan /dev/random
. Bukan OpenSSL (atau PRNGs userspace lainnya).Sebagai contoh:
#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()
aman secara kriptografis dan tidak bias.
sodium_init()
di beberapa titik. Jangan khawatir tentang RNG, karena menggunakan kernel.
sodium_init()
walaupun itu belum tentu menjadi bagian dari contoh saya karena ini merupakan detail penting.
Mari kita pergi melalui ini. Pertama-tama kita menggunakan fungsi srand () untuk seed randomizer. Pada dasarnya, komputer dapat menghasilkan angka acak berdasarkan nomor yang diumpankan ke srand (). Jika Anda memberikan nilai seed yang sama, maka angka acak yang sama akan dihasilkan setiap waktu.
Oleh karena itu, kita harus menyemai randomizer dengan nilai yang selalu berubah. Kami melakukan ini dengan memberinya nilai waktu saat ini dengan fungsi time ().
Sekarang, ketika kita memanggil rand (), nomor acak baru akan dihasilkan setiap saat.
#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) gagal saat hi_num - low_num > INT_MAX
. 3) Menghilangkan nilai dalam situasi yang jarang terjadi INT_MAX > hi_num - low_num > RAND_MAX
.
hi_num = max_num + 1;
tidak memiliki perlindungan terhadap luapan.
Jika Anda membutuhkan nomor acak semu yang lebih baik daripada yang stdlib
disediakan, periksa Mersenne Twister . Lebih cepat juga. Implementasi sampel berlimpah, misalnya di sini .
Fungsi standar C adalah rand()
. Cukup bagus untuk menangani kartu untuk solitaire, tapi itu mengerikan. Banyak implementasi rand()
siklus melalui daftar angka pendek, dan bit rendah memiliki siklus yang lebih pendek. Cara beberapa program menyebutnya rand()
mengerikan, dan menghitung benih yang baik untuk dilewatkan srand()
adalah sulit.
Cara terbaik untuk menghasilkan angka acak dalam C adalah dengan menggunakan perpustakaan pihak ketiga seperti OpenSSL. Sebagai contoh,
#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;
}
Mengapa begitu banyak kode? Bahasa lain seperti Java dan Ruby memiliki fungsi untuk bilangan bulat acak atau float. OpenSSL hanya memberikan byte acak, jadi saya mencoba untuk meniru bagaimana Java atau Ruby akan mengubahnya menjadi bilangan bulat atau mengapung.
Untuk bilangan bulat, kami ingin menghindari bias modulo . Misalkan kita mendapatkan beberapa bilangan bulat 4 digit acak rand() % 10000
, tetapi rand()
hanya dapat mengembalikan 0 hingga 32767 (seperti halnya di Microsoft Windows). Setiap angka dari 0 hingga 2767 akan muncul lebih sering daripada setiap angka dari 2768 hingga 9999. Untuk menghapus bias, kita dapat mencoba lagi rand()
sementara nilainya di bawah 2768, karena nilai-nilai 30000 dari 2768 hingga 32767 memetakan secara seragam ke nilai 10000 dari 0 hingga 9999.
Untuk mengapung, kami ingin 53 bit acak, karena double
memegang 53 bit presisi (dengan asumsi itu adalah ganda IEEE). Jika kita menggunakan lebih dari 53 bit, kita mendapatkan bias pembulatan. Beberapa programmer menulis kode seperti rand() / (double)RAND_MAX
, tetapi rand()
mungkin mengembalikan hanya 31 bit, atau hanya 15 bit di Windows.
RAND_bytes()
Benih OpenSSL sendiri, mungkin dengan membaca /dev/urandom
di Linux. Jika kita memerlukan banyak angka acak, akan terlalu lambat untuk membacanya /dev/urandom
, karena mereka harus disalin dari kernel. Lebih cepat untuk memungkinkan OpenSSL menghasilkan lebih banyak angka acak dari sebuah seed.
Lebih lanjut tentang angka acak:
srand()
. Ini mencampur bit dari waktu saat ini, ID proses, dan beberapa petunjuk, jika tidak bisa membaca /dev/urandom
.float
/ double
, jadi saya telah mengklarifikasi pertanyaan untuk tetap berpegang pada int
angka untuk menghindari membuatnya terlalu luas. Ada pertanyaan C lain yang berhubungan secara khusus dengan float
/ double
nilai acak, jadi Anda mungkin ingin memposting ulang bagian kedua dari jawaban Anda untuk pertanyaan seperti stackoverflow.com/questions/13408990/…
Jika sistem Anda mendukung arc4random
keluarga fungsi, saya akan merekomendasikan menggunakan rand
fungsi standar saja .
The arc4random
keluarga meliputi:
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
mengembalikan bilangan bulat unsigned 32-bit acak.
arc4random_buf
menempatkan konten acak di parameternya buf : void *
. Jumlah konten ditentukan oleh bytes : size_t
parameter.
arc4random_uniform
mengembalikan bilangan bulat 32-bit unsigned acak yang mengikuti aturan:, di 0 <= arc4random_uniform(limit) < limit
mana batasnya juga merupakan integer 32-bit yang tidak ditandatangani.
arc4random_stir
membaca data dari /dev/urandom
dan meneruskan data arc4random_addrandom
ke juga mengacak kumpulan angka acak internal itu.
arc4random_addrandom
digunakan oleh arc4random_stir
untuk mengisi kumpulan nomor acak internal itu menurut data yang diteruskan ke sana.
Jika Anda tidak memiliki fungsi-fungsi ini, tetapi Anda berada di Unix, maka Anda dapat menggunakan kode ini:
/* 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;
}
The urandom_init
Fungsi membuka /dev/urandom
perangkat, dan menempatkan file descriptor di urandom_fd
.
The urandom
Fungsi dasarnya adalah sama sebagai panggilan untuk rand
, kecuali lebih aman, dan mengembalikan long
(mudah berubah).
Namun, /dev/urandom
bisa sedikit lambat, sehingga Anda disarankan menggunakannya sebagai seed untuk generator angka acak yang berbeda.
Jika sistem Anda tidak memiliki /dev/urandom
, tapi tidak memiliki /dev/random
atau file yang sama, maka Anda hanya bisa mengubah jalan dilewatkan ke open
dalam urandom_init
. Panggilan dan API yang digunakan dalam urandom_init
dan urandom
(saya percaya) POSIX-compliant, dan dengan demikian, harus bekerja pada sebagian besar, jika tidak semua sistem yang sesuai dengan POSIX.
Catatan: Pembacaan dari /dev/urandom
TIDAK akan memblokir jika ada cukup entropi yang tersedia, sehingga nilai yang dihasilkan dalam keadaan seperti itu mungkin tidak aman secara kriptografis. Jika Anda khawatir tentang itu, maka gunakan /dev/random
, yang akan selalu memblokir jika ada cukup entropi.
Jika Anda berada di sistem lain (yaitu Windows), maka gunakan rand
atau API non-portabel yang bergantung pada platform khusus Windows internal.
Wrapper fungsi untuk urandom
, rand
atau arc4random
panggilan:
#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
int myRandom(int bottom, int top){
return (RAND_IMPL() % (top - bottom)) + bottom;
}
STL tidak ada untuk C. Anda harus menelepon rand
, atau lebih baik lagi random
,. Ini dideklarasikan di header perpustakaan standar stdlib.h
. rand
adalah POSIX, random
adalah fungsi spesifikasi BSD.
Perbedaan antara rand
dan random
adalah yang random
mengembalikan angka acak 32-bit yang lebih dapat digunakan, dan rand
biasanya mengembalikan angka 16-bit. Halaman manual BSD menunjukkan bahwa bit yang lebih rendah rand
bersifat siklik dan dapat diprediksi, sehingga rand
berpotensi tidak berguna untuk jumlah kecil.
extern int rand(void);
dan extern void srand(unsigned int);
.
Lihatlah ISAAC (Indirection, Shift, Accumulate, Add, and Count). Didistribusikan secara seragam dan memiliki panjang siklus rata-rata 2 ^ 8295.
Ini adalah cara yang baik untuk mendapatkan angka acak antara dua angka pilihan Anda.
#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));
}
Keluaran pertama kali: 39
Keluaran untuk kedua kalinya: 61
Keluaran yang ketiga kalinya: 65
Anda dapat mengubah nilai setelah randnum
ke nomor apa pun yang Anda pilih, dan itu akan menghasilkan angka acak untuk Anda di antara dua angka itu.
Anda ingin menggunakan rand()
. Catatan ( SANGAT PENTING ): pastikan untuk mengatur seed untuk fungsi rand. Jika tidak, angka acak Anda tidak benar-benar acak . Ini sangat, sangat, sangat penting. Untungnya, Anda biasanya dapat menggunakan beberapa kombinasi pengingat waktu sistem dan tanggal untuk mendapatkan seed yang bagus.
FWIW, jawabannya adalah ya, ada stdlib.h
fungsi yang disebut rand
; fungsi ini disetel terutama untuk kecepatan dan distribusi, bukan untuk ketidakpastian. Hampir semua fungsi acak bawaan untuk berbagai bahasa dan kerangka kerja menggunakan fungsi ini secara default. Ada juga generator nomor acak "kriptografi" yang jauh lebih mudah diprediksi, tetapi berjalan jauh lebih lambat. Ini harus digunakan dalam segala jenis aplikasi yang berhubungan dengan keamanan.
Mudah-mudahan ini sedikit lebih acak daripada hanya menggunakan 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 adalah C ++, bukan C, jadi saya tidak tahu apa yang Anda inginkan. Namun, jika Anda menginginkan C, ada rand()
dan srand()
fungsinya:
int rand(void);
void srand(unsigned seed);
Keduanya adalah bagian dari ANSI C. Ada juga random()
fungsinya:
long random(void);
Tapi sejauh yang saya tahu, random()
itu bukan standar ANSI C. Perpustakaan pihak ketiga mungkin bukan ide yang buruk, tetapi semuanya tergantung pada seberapa acak angka yang benar-benar Anda butuhkan untuk menghasilkan.
Program C untuk menghasilkan angka acak antara 9 dan 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);
}
Secara umum kita dapat menghasilkan angka acak antara lowerLimit dan upperLimit-1
yaitu lowerLimit termasuk atau katakan r ∈ [lowerLimit, upperLimit)
rand()
adalah cara paling mudah untuk menghasilkan angka acak.
Anda juga dapat memperoleh nomor acak dari layanan online seperti random.org.
#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;
}
Pada CPU x86_64 modern Anda dapat menggunakan generator nomor acak perangkat keras via _rdrand64_step()
Kode contoh:
#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;
}
Mendengar penjelasan yang baik tentang mengapa menggunakan rand()
untuk menghasilkan angka acak yang terdistribusi secara seragam dalam rentang yang diberikan adalah ide yang buruk, saya memutuskan untuk melihat bagaimana kemiringan output sebenarnya. Kasus tes saya adalah melempar dadu dengan adil. Ini kode C:
#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);
}
dan inilah hasilnya:
$ 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%
Saya tidak tahu seberapa seragam Anda perlu nomor acak Anda, tetapi di atas tampak cukup seragam untuk sebagian besar kebutuhan.
Sunting: itu akan menjadi ide yang baik untuk menginisialisasi PRNG dengan sesuatu yang lebih baik daripada time(NULL)
.
Saya memiliki masalah serius dengan pseudo random generator angka dalam aplikasi saya baru-baru ini: Saya berulang kali memanggil program C saya melalui skrip pyhton dan saya gunakan sebagai seed kode berikut:
srand(time(NULL))
Namun, sejak:
man srand
);time
akan mengembalikan nilai yang sama setiap kali.Program saya menghasilkan urutan angka yang sama. Anda dapat melakukan 3 hal untuk menyelesaikan masalah ini:
mencampur output waktu dengan beberapa informasi lain yang berubah saat berjalan (dalam aplikasi saya, nama output):
srand(time(NULL) | getHashOfString(outputName))
Saya menggunakan djb2 sebagai fungsi hash saya.
Tambah resolusi waktu. Di platform saya, clock_gettime
tersedia, jadi saya menggunakannya:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec);
Gunakan kedua metode bersama-sama:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec | getHashOfString(outputName));
Opsi 3 memastikan Anda (sejauh yang saya tahu) keacakan benih terbaik, tetapi mungkin membuat perbedaan hanya pada aplikasi yang sangat cepat. Menurut saya opsi 2 adalah taruhan yang aman.
rand()
tidak boleh digunakan untuk data kriptografi, saya setuju. Setidaknya bagi saya, aplikasi saya tidak melibatkan data kriptografi, jadi bagi saya itu ok metode yang diberikan.
Terlepas dari semua saran orang di rand()
sini, Anda tidak ingin menggunakan rand()
kecuali Anda harus! Angka acak yang rand()
menghasilkan seringkali sangat buruk. Mengutip dari halaman manual Linux:
Versi
rand()
dansrand()
di Linux C Library menggunakan generator angka acak yang sama denganrandom(3)
dansrandom(3)
, sehingga bit urutan rendah harus acak seperti bit urutan yang lebih tinggi. Namun, pada implementasi rand () lama, dan pada implementasi saat ini pada sistem yang berbeda, bit orde rendah jauh lebih sedikit acak daripada bit orde tinggi . Jangan gunakan fungsi ini dalam aplikasi yang dimaksudkan untuk portabel ketika keacakan yang baik diperlukan. ( Gunakanrandom(3)
saja. )
Mengenai portabilitas, random()
juga ditentukan oleh standar POSIX untuk beberapa waktu sekarang. rand()
lebih tua, sudah muncul di spec POSIX.1 pertama (IEEE Std 1003.1-1988), sedangkan yang random()
pertama muncul di POSIX.1-2001 (IEEE Std 1003.1-2001), namun standar POSIX saat ini sudah POSIX.1-2008 (IEEE Std 1003.1-2008), yang menerima pembaruan setahun yang lalu (IEEE Std 1003.1-2008, Edisi 2016). Jadi saya akan mempertimbangkanrandom()
sangat portabel.
POSIX.1-2001 juga memperkenalkan lrand48()
dan mrand48()
fungsinya, lihat di sini :
Rangkaian fungsi ini akan menghasilkan angka pseudo-acak menggunakan algoritma linear kongruensial dan aritmatika integer 48-bit.
Dan sumber acak semu yang cukup bagus adalah arc4random()
fungsi yang tersedia di banyak sistem. Bukan bagian dari standar resmi apa pun, muncul di BSD sekitar tahun 1997 tetapi Anda dapat menemukannya di sistem seperti Linux dan macOS / iOS.
random()
tidak ada di Windows.
rand()
karena juga diperlukan oleh standar C. Untuk hal lain, Anda memerlukan solusi khusus untuk Windows saja, seperti biasa. #ifdef _WIN32
adalah ungkapan yang paling sering Anda lihat dalam kode lintas platform yang ingin mendukung Windows dan biasanya ada satu solusi yang bekerja dengan semua sistem dan satu yang diperlukan untuk Windows saja.
Untuk aplikasi Linux C:
Ini adalah kode ulang saya dari jawaban di atas yang mengikuti praktik kode C saya dan mengembalikan buffer acak dalam berbagai ukuran (dengan kode pengembalian yang tepat, dll.). Pastikan untuk menelepon urandom_open()
sekali di awal program Anda.
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;
}
}
Solusi minimalis saya harus bekerja untuk angka acak dalam jangkauan [min, max)
. Gunakan srand(time(NULL))
sebelum memanggil fungsi.
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));
}
Coba ini, saya menggabungkannya dari beberapa konsep yang telah dirujuk di atas:
/*
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()
setiap kali Anda ingin menelepon rand()
adalah ide yang buruk. Karena time()
biasanya mengembalikan nilai dalam hitungan detik yang memanggil fungsi ini dengan cepat akan mengembalikan nilai "acak" yang sama.
random()
fungsi Unix .