Random Number Generator not working - c

I use this function to create random numbers between 100000000 and 999999999
int irand(int start, int stop) {
double range = stop - start + 1;
return start + (int)(range * rand()/(RAND_MAX+1.0));
}
When I use it like this, it's properly working
while(1) {
DWORD dw = irand(100000000, 999999999);
printf("dynamic key: %d\n", dw);
Sleep(100);
}
But when I use this function without the while(1), I always get the same number.
What do I need to fix?

The random number generator must be seeded with some source of entropy for you to see different sequences each time, otherwise an initial seed value of 1 is used by the rand function. In your case, calling srand (time(NULL)); once before the irand function is first called should do the trick. You might find this question useful: why do i always get the same sequence of random numbers with rand() ?

Not a direct answer to your question, but something you should probably read if you're struggling with random numbers. This recent article by our very own Jon Skeet is a good intro to random numbers and the trubles one might run into: http://csharpindepth.com/Articles/Chapter12/Random.aspx

Related

Shuffling an array

What this code is supposed to do is shuffle an array, nonetheless every time I run it on a I get the same "shuffled" array (of course by inputting the same un-shuffled array) I thought the srand(time(NULL)); part was going to make sure of that. If that is not it I don’t know how to make it really shuffle it.
So to sum up I need to know why my code is shuffling the array the same way every time.
# include <stdio.h>
# include <stdlib.h>
# include <math.h>
# include <time.h>
int main(){
int n;
int m;
int tmp;
int i;
printf("Please input the number of elements in your array:\n");
scanf("%d", &n);
int baraja[n];
int tempbaraja[n];
for (int i = 0; i < (sizeof(baraja)/sizeof(baraja[0])); i ++){
printf("Please input the %d element of your array:\n",i);
scanf("%d",&baraja[i]);
}
printf("Unshuffled array:\n");
for (i=0;i < n;i++) {
printf(" %d \n",baraja[i]);
}
for (int i = 0; i < n; i ++){
tempbaraja[i] = baraja[i];
}
for (int i = 0; i < n; i ++){
srand(time(NULL));
m = rand() % n;
if (tempbaraja[m] == baraja[m]){
tmp = baraja[m];
baraja[m] = baraja[i];
baraja[i] = tmp;
}else{
}
}
printf("Shuffled array:\n");
for (i=0;i < n;i++) {
printf(" %d \n",baraja[i]);
}
}
You need to move srand(time(NULL)); outside the for loop.
If you see, rand() is a pseudo-random number generator. srand() is used to provide the seed based on which the random number will be generated by rand().
If every time you seed with the same time(NULL) before each call to rand(), each outcome of rand() is going to be the same.
To achieve the desired result, you need to seed the random number generator only once using srand() and later on each call of rand(), it will give you the random numbers.
Note: Though it is not mandatory, it's good practice to have an explicit return 0 at the end of main().
Get srand(time(NULL)) out of the loop.
From srand reference:
Two different initializations with the same seed will generate the
same succession of results in subsequent calls to rand.
So for each iteration you are initializing the random number generator and getting the first item, which is always the same.
You're misusing srand, it should only be called once outside of the loop. These is also a chance that the srand and rand implementations may be particularly bad on the platform you're running on, leading to poor performance if the program is re-executed quickly.
Alright, I'll answer the followup question. Why is srand() in a loop bad?
The rand() function produces a sequence of acceptably random numbers, without needing srand() at all. The problem is that it's a fixed sequence, so every time you run the program, you'll get the same set of "random" numbers.
The goal of srand(time(NULL)) is to pick a starting value different from any previous starting value. The time() function call is only being used to pick a different starting point, with the drawback that the result only changes once per second. Running the program twice in the same second can be a problem with programs launched from a script file or batch job, but usually not when launched from keyboard or mouse events.
So, using srand(time(NULL)) in the loop has one major evil effect. You only get one new random number every wall-clock second.
Even if you had a high-precision timer to sample from, or used:
unsigned counter = time(NULL);
srand(counter++);
..to choose a different starting value, there are still problems. The distribution of random number chosen from sequential starting points is not as "random" as the overall sequence, and may be quite bad for some generators. If you had a source of starting points that was random enough to give good result from srand();rand();, then you probably wouldn't need rand() at all. You could just use those starting values directly!
Finally, srand() slows down your program. Visual C++ in particular has notoriously slow rand() and srand(), and MinGW uses that library too. (The technical issue is due to storing the seed value in thread local storage, which takes over 100 instructions to find on each call.) However, even a statically linked non-thread-safe version involves an extra call and return that you don't need.
Those are the major reasons that I know of for not using srand() in a loop. Most developers would be happy with "it's not necessary".
The glibc srand() manual page, which states: "The srand() function sets its argument as the seed for a new sequence of pseudo-random integers to be returned by rand(). These sequences are repeatable by calling srand() with the same seed value." Specifically your program potentially violated the clause : "..sequences are repeatable by calling srand() with the same seed value." because it could seed rand() more than once per second with the time -- resulting in identical pseudo-random number sequences.

How to write a random generator function without using time functions, static variables or global variables?

How to write a random generator function without using standard C functions like time functions, static variables or global variables?
/* #include <time.h> Don't use time functions. */
/* int seed = 1234; Don't use global variables. */
int generate_random(void)
{
/* static int seed = 1234; Don't use static variables. */
/* return (time() % 100); Don't use time functions. */
}
In other words, this random generator function should not remember the last state.
you can also use srand by
#include<stdlib.h>
srand(getpid());
int num = rand();
This solution meets all your criterion, but it does require the Internet.*
unsigned generate_random () {
FILE *random;
char cmd[512];
unsigned number;
snprintf(cmd, sizeof(cmd),
"wget -qO - "
"'http://www.random.org/integers/"
"?num=1&min=0&max=%u&col=1&base=10&format=plain&rnd=new'",
USHRT_MAX);
random = popen(cmd, "r");
fscanf(random, "%u", &number);
pclose(random);
return number;
}
*That's not really a mark against the algorithm, though, since the Internet is an excellent source of random data. ;-)
Assuming you need to do your own pseudo-random number generator,
you need to remember the state.
If function shouldn't remember last state, you need to pass it as an argument:
int generate_random(int * lastState)
{
// generate next random from lastState
// store state to lastState
// return result
}
int main(void)
{
int lastState = 1234; // seed it
int random = generate_random(&lastState);
}
do
#include <time.h>
#include <stdlib.h>
srand(time(NULL));
int r = rand();
if you want to limit the number use
int r = minNum + rand() % maxNum;
do not try to create your own random function. it will not end well
Guessing about your question...I have to ask what is the requirement for wanting a random seed?
Being able to set the seed value is a plus for code because you at least try to do things like regression testing.
If your question is about random numbers in general. There are two steps needed to generate a series of random numbers.
First, set a seed value, for example, srand(1234); where 1234 is the seed value. Your code only issues this instruction once. When you run the program a second time your code can re-use the same seed value, in which case the sequence of random numbers will be the same. If you set a different seed, then you will get a different sequence of random numbers.
The second step is to retrieve the random number values for use in your code.
One Possible Method
In theory, you could use a fixed seed value and then generate R random numbers, where R is some number taken from the system mod 100 (for example). Then use that R'th random number as the seed value for the actual sequence of random numbers for your application.
You say that you don't want to use Time(), but maybe in this double sequence of random numbers and the Time() mod n function will provide enough randomness.
Now, I say in theory, because random numbers from rand() are actually psuedo-random and for all intents and purposes they really are random (guys with math PhDs say this...), so I doubt if doing this "double selection" will make the numbers more random. But, this method or one like it might make a reviewer or boss feel more comfortable, but this would be a false sense of security.

Where in this code generates a random number?

I came across rgba's floating point random number generator:
http://rgba.org/articles/sfrand/sfrand.htm
The explanation is clear and the code is simple. There is one issue: I cannot figure out where the random bits come from. Code snippet below:
static unsigned int mirand = 1;
float sfrand( void )
{
unsigned int a;
mirand *= 16807;
a = (mirand&0x007fffff) | 0x40000000;
return( *((float*)&a) - 3.0f );
}
I did try to compile this function and always get a result of -0.995993, which makes sense if mirand starts out as 1. What am I missing, or is mirand simply the seed?
Truth is, that code does NOT generate random numbers... it generates pseudo-random numbers. Assuming you start with the same seed, a layman's way to imagine what's happening is that you are just going through a HUGE list of "random" numbers. Eventually, the numbers will repeat themselves, but a good formula is one that makes this repetition happen at a large interval.
To clarify, take a look at the rand formula that Excel uses: http://support.microsoft.com/kb/828795
The reason you're getting the same number every time is because this is in fact a pseudo random number generator just like regular ones. It has no seed so you will always get the same value on the nth call. If you make several subsequent calls to sfrand you'll see the results, which are uniform between -1 and 1:
-0.995993
0.347347
-0.130602
0.970146
-0.749159
0.883045
Just like if you were to call the normal rand() function without seeding it you'd see the same sequence. As discussed the number 16807 was chosen for good reason, so you can seed this number by calling the function a random number of times:
static unsigned int mirand = 1;
float sfrand(double seed)
{
unsigned int a;
mirand *= seed;
a = (mirand&0x007fffff) | 0x40000000;
return( *((float*)&a) - 3.0f );
}
int main()
{
srand(time(NULL));
int count = rand() % 1000 + 1
for(int i = 0; i < count; ++i)
sfrand();
}
This will just discard the first count values while still giving you a random seed, and all subsequent calls will still gain the performance boost intended by the function. Subsequent calls now return unique values:
codys-macbook-pro:~ cody$ ./a.out
0.166836
codys-macbook-pro:~ cody$ ./a.out
0.256372
codys-macbook-pro:~ cody$ ./a.out
-0.194259
codys-macbook-pro:~ cody$ ./a.out
-0.556834

using rand to generate a random numbers

gcc 4.4.4 c89
I am using the code below. However, I keep getting the same number:
size_t i = 0;
for(i = 0; i < 3; i++) {
/* Initialize random number */
srand((unsigned int)time(NULL));
/* Added random number (simulate seconds) */
add((rand() % 30) + 1);
}
I would like to get 0 to 30 returned. However, the last time I ran this I got 17 three times.
Many thanks,
You're seeding inside the loop (with the same value because of how quickly the loop will be executed), which causes the random number generated to be the same each time.
You need to move your seed function outside the loop:
/* Initialize random number */
srand((unsigned int)time(NULL));
for(i = 0; i < 3; i++) {
/* Added random number (simulate seconds) */
add((rand() % 30) + 1);
}
You need to call srand just once, at the beginning of your program.
srand initializes the pseudo random number generator using time in seconds. If you initialize it with a particular number, you will always get the same sequence of numbers. That's why you usually want to initialize it at the beginning using the time (so that the seed is different each time you run the program) and then use only rand to generate numbers which seem random.
In your case the time does not change from iteration to iteration, as its resolution is just 1 second, so you are always getting the first number of the pseudo-random sequence, which is always the same.
You need to do srand((unsigned int)time(NULL)) only once before the loop.
It is completely possible that the 3 times 17 are still completely random.
There is an about 1 in 10 chance of getting two numbers the same when using a range of 1-30 and three picks. (this is due to the birthday problem )
Now, getting three the same results has still a propability of 1 in 900 using the same range.
you might want to read more background on the analysis page of random.org
Seed to the pseudo Random number generator should be called only once outside the loop. Using time as a seed is good thing.
However there is still a possiblity of getting the same random number.
I rather suggest also using gettimeofday() system call to retrieve the seed to be used to feed srand().
Something like
struct timeval tv;
...
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
...
This approach can add more entropy in your pseudo number generation code.
IMHO of course
Ciao ciao

Generating random numbers in C

I know this question has been asked time and again. I need random numbers between 0-9. I am using the following code:
srand(time());
int r;
for (;;)
{
while(condition)
{
r = rand()%10;
// ...
// ...
}
}
Now I am getting the same sequence of numbers for each iteration of for loop. Can someone provide me the correct code?
PS - My compiler doesn't recognize arcrandom().
This problem stems from the fact that on some implementations the lower-order bits of rand() are not very random. Quoting from the man page:
"If you want to generate a random integer between 1 and 10, you should always do it by using high-order bits, as in
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
and never by anything resembling
j = 1 + (rand() % 10);
(which uses lower-order bits)."
You're probably calling this function within the second, and srand is going to get seeded with the same second. You should only call srand once at the beginning of main.
Many pseudorandom generators have an observable period. If you need a long period consider using the algorithm from Knuth 2.
It has a period of about 2^55, and is simple to implement.
RANARRAY
Remove all srand() calls from your code.
Add one, unique call right before the first statement in main().
int main(void) {
int foo = 42;
int bar = baz(42);
srand(time(0));
/* rest of your program */
return 0;
}
Your code doesn't compile -- for() is not valid C.
Are you sure that you are calling srand only once, at the start of the program and before any rand calls? Calling srand within the loop would explain this behavior.
srand(time(0));
r = rand() % (max+1);
//r will be a random number between 0 and max.
I can only think that you did not initialize correctly, or your redacted code is redacted wrongly.
Have you random()?
random() man page
I have made simple program:
int i;
for(i=0;i<40;i++)
printf("%d",rand()%10);
And geting 7938024839052273790239970398657627039991 - no repeating here.
How long is your sequence?
Depending on your requirements for statistical randomness you might find it better to ditch the psuedo random number generator and try an external source.
random.org and randomnumbers.info (amongst others) will provide truly random numbers for download, which libcurl should handle for you.
The only possible way you could be getting the exact same sequence of numbers is if there is a call to srand() somewhere in the code that you haven't shown us. It could be deep within a function call somewhere.
The proper way to fix this would be to find the extra call to srand and remove it. However this quick hack might get you started:
static int seed = time();
int r;
for (;;)
{
srand(seed++);
while(condition)
{
r = rand()%10;
// ...
// ...
}
}

Resources