Is there a function to generate a random int number in C? Or will I have to use a third party library?
相关问题
- Multiple sockets for clients to connect to
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- Index of single bit in long integer (in C) [duplic
- Equivalent of std::pair in C
I had a serious issue with pseudo random number generator in my recent application: I repeatidly called my C program via a pyhton script and I was using as seed the following code:
However, since:
man srand
);time
will return the same value each time.My program generated the same sequence of numbers. You can do 3 things to solve this problem:
mix time output with some other information changing on runs (in my application, the output name):
I used djb2 as my hash function.
Increase time resolution. On my platform,
clock_gettime
was available, so I use it:Use both methods together:
Option 3 ensures you (as far as i know) the best seed randomity, but it may create a difference only on very fast application. In my opinion option 2 is a safe bet.
The standard C function is
rand()
. It's good enough to deal cards for solitaire, but it's awful. Many implementations ofrand()
cycle through a short list of numbers, and the low bits have shorter cycles. The way that some programs callrand()
is awful, and calculating a good seed to pass tosrand()
is hard.The best way to generate random numbers in C is to use a third-party library like OpenSSL. For example,
Why so much code? Other languages like Java and Ruby have functions for random integers or floats. OpenSSL only gives random bytes, so I try to mimic how Java or Ruby would transform them into integers or floats.
For integers, we want to avoid modulo bias. Suppose that we got some random 4 digit integers from
rand() % 10000
, butrand()
can only return 0 to 32767 (as it does in Microsoft Windows). Each number from 0 to 2767 would appear more often than each number from 2768 to 9999. To remove the bias, we can retryrand()
while the value is below 2768, because the 30000 values from 2768 to 32767 map uniformly onto the 10000 values from 0 to 9999.For floats, we want 53 random bits, because a
double
holds 53 bits of precision (assuming it's an IEEE double). If we use more than 53 bits, we get rounding bias. Some programmers write code likerand() / (double)RAND_MAX
, butrand()
might return only 31 bits, or only 15 bits in Windows.OpenSSL's
RAND_bytes()
seeds itself, perhaps by reading/dev/urandom
in Linux. If we need many random numbers, it would be too slow to read them all from/dev/urandom
, because they must be copied from the kernel. It is faster to allow OpenSSL to generate more random numbers from a seed.More about random numbers:
srand()
. It mixes bits from the current time, the process ID, and some pointers, if it can't read/dev/urandom
.This is hopefully a bit more random than just using
srand(time(NULL))
.Have a look at ISAAC (Indirection, Shift, Accumulate, Add, and Count). Its uniformly distributed and has an average cycle length of 2^8295.
This is a good way to get a random number between two numbers of your choice.
Output the first time: 39
Output the second time: 61
Output the third time: 65
You can change the values after
randnum
to whatever numbers you choose, and it will generate a random number for you between those two numbers.