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
Related
If you wanted a random number generator to use ints 2,5,7,4 and you seed your generator with
srand(2,5,7,4)
printf("%d \n",rand())
Is this flawed in accomplishing that?
That is not how it works. An PRNG uses an algorithm to generate a sequence of numbers with random like behaviour. For a given seed, a given sequence of numbers will be generated, what those number are is entirely up to the algorithm used.
to get a random number for a list, you will need something like:
n = list[rand() % (sizeof(list) / sizeof(list[0])];
In case you want to print a value from a given array randomly on each execution, you may consider using the following:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main() {
srand ( time(NULL) ); // accepts one argument only
int myArray[4] = { 2,5,7,4 }; // array required
int randomIndex = rand() % 4; // limiting randomness
int randomValue = myArray[randomIndex]; // choosing one of the random numbers
printf("Random value from array: %d\n", randomValue); // simply prints
return 0;
}
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.
While searching for Tutorials on generating random numbers in C I found this topic
When I try to use the rand() function without parameters, I always get 0. When I try to use the rand() function with parameters, I always get the value 41. And whenever I try to use arc4random() and random() functions, I get a LNK2019 error.
Here's what I've done:
#include <stdlib.h>
int main()
{
int x;
x = rand(6);
printf("%d", x);
}
This code always generates 41. Where am I going wrong? I'm running Windows XP SP3 and using VS2010 Command Prompt as compiler.
You should call srand() before calling rand to initialize the random number generator.
Either call it with a specific seed, and you will always get the same pseudo-random sequence
#include <stdlib.h>
int main ()
{
srand ( 123 );
int random_number = rand();
return 0;
}
or call it with a changing sources, ie the time function
#include <stdlib.h>
#include <time.h>
int main ()
{
srand ( time(NULL) );
int random_number = rand();
return 0;
}
In response to Moon's Comment
rand() generates a random number with an equal probability between 0 and RAND_MAX (a macro pre-defined in stdlib.h)
You can then map this value to a smaller range, e.g.
int random_value = rand(); //between 0 and RAND_MAX
//you can mod the result
int N = 33;
int rand_capped = random_value % N; //between 0 and 32
int S = 50;
int rand_range = rand_capped + S; //between 50 and 82
//you can convert it to a float
float unit_random = random_value / (float) RAND_MAX; //between 0 and 1 (floating point)
This might be sufficient for most uses, but its worth pointing out that in the first case using the mod operator introduces a slight bias if N does not divide evenly into RAND_MAX+1.
Random number generators are interesting and complex, it is widely said that the rand() generator in the C standard library is not a great quality random number generator, read (http://en.wikipedia.org/wiki/Random_number_generation for a definition of quality).
http://en.wikipedia.org/wiki/Mersenne_twister (source http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html ) is a popular high quality random number generator.
Also, I am not aware of arc4rand() or random() so I cannot comment.
You need to seed your PRNG so it starts with a different value each time.
A simple but low quality seed is to use the current time:
srand(time(0));
This will get you started but is considered low quality (i.e. for example, don't use that if you are trying to generate RSA keys).
Background. Pseudo-random number generators do not create true random number sequences but just simulate them. Given a starting point number, a PRNG will always return the same sequence of numbers. By default, they start with the same internal state so will return the same sequence.
To not get the same sequence, you change the internal state. The act of changing the internal state is called "seeding".
#include <stdlib.h>
int main()
{
int x;
x = rand(6);
printf("%d", x);
}
Especially as a beginner, you should ask your compiler to print every warning about bad code that it can generate. Modern compilers know lots of different warnings which help you to program better. For example, when you compile this program with the GNU C Compiler:
$ gcc -W -Wall rand.c
rand.c: In function `main':
rand.c:5: error: too many arguments to function `rand'
rand.c:6: warning: implicit declaration of function `printf'
You get two warnings here. The first one says that the rand function only takes zero arguments, not one as you tried. To get a random number between 0 and n, you can use the expression rand() % n, which is not perfect but ok for small n. The resulting random numbers are normally not evenly distributed; smaller values are returned more often.
The second warning tells you that you are calling a function that the compiler doesn't know at that point. You have to tell the compiler by saying #include <stdio.h>. Which include files are needed for which functions is not always simple, but asking the Open Group specification for portable operating systems works in many cases: http://www.google.com/search?q=opengroup+rand.
These two warnings tell you much about the history of the C programming language. 40 years back, the definition of a function didn't include the number of parameters or the types of the parameters. It was also ok to call an unknown function, which in most cases worked. If you want to write code today, you should not rely on these old features but instead enable your compiler's warnings, understand the warnings and then fix them properly.
Also, linear congruential PRNGs tend to produce more randomness on the higher bits that on the lower bits, so to cap the result don't use modulo, but instead use something like:
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
(This one is from "Numerical Recipes in C", ch.7)
You first need to seed the generator because it doesn't generate real random numbers!
Try this:
#include <stdlib.h>
#include <time.h>
int main()
{
// random seed, time!
srand( time(NULL) ); // hackish but gets the job done.
int x;
x = rand(); // everytime it is different because the seed is different.
printf("%d", x);
}
Or, to get a pseudo-random int in the range 0 to 19,
for example, you could use the higher bits like this:
j = ((rand() >> 15) % 20;
int *generate_randomnumbers(int start, int end){
int *res = malloc(sizeof(int)*(end-start));
srand(time(NULL));
for (int i= 0; i < (end -start)+1; i++){
int r = rand()%end + start;
int dup = 0;
for (int j = 0; j < (end -start)+1; j++){
if (res[j] == r){
i--;
dup = 1;
break;
}
}
if (!dup)
res[i] = r;
}
return res;
}
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
While searching for Tutorials on generating random numbers in C I found this topic
When I try to use the rand() function without parameters, I always get 0. When I try to use the rand() function with parameters, I always get the value 41. And whenever I try to use arc4random() and random() functions, I get a LNK2019 error.
Here's what I've done:
#include <stdlib.h>
int main()
{
int x;
x = rand(6);
printf("%d", x);
}
This code always generates 41. Where am I going wrong? I'm running Windows XP SP3 and using VS2010 Command Prompt as compiler.
You should call srand() before calling rand to initialize the random number generator.
Either call it with a specific seed, and you will always get the same pseudo-random sequence
#include <stdlib.h>
int main ()
{
srand ( 123 );
int random_number = rand();
return 0;
}
or call it with a changing sources, ie the time function
#include <stdlib.h>
#include <time.h>
int main ()
{
srand ( time(NULL) );
int random_number = rand();
return 0;
}
In response to Moon's Comment
rand() generates a random number with an equal probability between 0 and RAND_MAX (a macro pre-defined in stdlib.h)
You can then map this value to a smaller range, e.g.
int random_value = rand(); //between 0 and RAND_MAX
//you can mod the result
int N = 33;
int rand_capped = random_value % N; //between 0 and 32
int S = 50;
int rand_range = rand_capped + S; //between 50 and 82
//you can convert it to a float
float unit_random = random_value / (float) RAND_MAX; //between 0 and 1 (floating point)
This might be sufficient for most uses, but its worth pointing out that in the first case using the mod operator introduces a slight bias if N does not divide evenly into RAND_MAX+1.
Random number generators are interesting and complex, it is widely said that the rand() generator in the C standard library is not a great quality random number generator, read (http://en.wikipedia.org/wiki/Random_number_generation for a definition of quality).
http://en.wikipedia.org/wiki/Mersenne_twister (source http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html ) is a popular high quality random number generator.
Also, I am not aware of arc4rand() or random() so I cannot comment.
You need to seed your PRNG so it starts with a different value each time.
A simple but low quality seed is to use the current time:
srand(time(0));
This will get you started but is considered low quality (i.e. for example, don't use that if you are trying to generate RSA keys).
Background. Pseudo-random number generators do not create true random number sequences but just simulate them. Given a starting point number, a PRNG will always return the same sequence of numbers. By default, they start with the same internal state so will return the same sequence.
To not get the same sequence, you change the internal state. The act of changing the internal state is called "seeding".
#include <stdlib.h>
int main()
{
int x;
x = rand(6);
printf("%d", x);
}
Especially as a beginner, you should ask your compiler to print every warning about bad code that it can generate. Modern compilers know lots of different warnings which help you to program better. For example, when you compile this program with the GNU C Compiler:
$ gcc -W -Wall rand.c
rand.c: In function `main':
rand.c:5: error: too many arguments to function `rand'
rand.c:6: warning: implicit declaration of function `printf'
You get two warnings here. The first one says that the rand function only takes zero arguments, not one as you tried. To get a random number between 0 and n, you can use the expression rand() % n, which is not perfect but ok for small n. The resulting random numbers are normally not evenly distributed; smaller values are returned more often.
The second warning tells you that you are calling a function that the compiler doesn't know at that point. You have to tell the compiler by saying #include <stdio.h>. Which include files are needed for which functions is not always simple, but asking the Open Group specification for portable operating systems works in many cases: http://www.google.com/search?q=opengroup+rand.
These two warnings tell you much about the history of the C programming language. 40 years back, the definition of a function didn't include the number of parameters or the types of the parameters. It was also ok to call an unknown function, which in most cases worked. If you want to write code today, you should not rely on these old features but instead enable your compiler's warnings, understand the warnings and then fix them properly.
Also, linear congruential PRNGs tend to produce more randomness on the higher bits that on the lower bits, so to cap the result don't use modulo, but instead use something like:
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
(This one is from "Numerical Recipes in C", ch.7)
You first need to seed the generator because it doesn't generate real random numbers!
Try this:
#include <stdlib.h>
#include <time.h>
int main()
{
// random seed, time!
srand( time(NULL) ); // hackish but gets the job done.
int x;
x = rand(); // everytime it is different because the seed is different.
printf("%d", x);
}
Or, to get a pseudo-random int in the range 0 to 19,
for example, you could use the higher bits like this:
j = ((rand() >> 15) % 20;
int *generate_randomnumbers(int start, int end){
int *res = malloc(sizeof(int)*(end-start));
srand(time(NULL));
for (int i= 0; i < (end -start)+1; i++){
int r = rand()%end + start;
int dup = 0;
for (int j = 0; j < (end -start)+1; j++){
if (res[j] == r){
i--;
dup = 1;
break;
}
}
if (!dup)
res[i] = r;
}
return res;
}