Python's random.uniform() in C++?
I've been ripping my hair out for a while now with these random numbers in C++.
In Python, I had the awesome:
random.uniform(0, 1)
Which churned out a new random number each time I called it.
C++ has to have something like this. I Googled for a long time, and found erand48()
, which I plan to implement into my raytracer (I'm translating it from Python to C++).
I tried a simple test case, but I was hoping to create a random_uniform()
function which always spits out a new random number (using time()
isn't going to work AFAICT, as this will be running really quickly)
unsigned short Xi[3] = {0, 1, 27};
std::cout << erand48(Xi);
And the output was (and will be every time I call the program):
0.174529
I tried using the previous output as the new Xi
, like this (Xi
s initial value was defined):
float random_uniform() {
long generated = erand48(Xi);
int temp = generated * 1000000;
unsigned short Xi[3] = {temp - 16, temp - 7, temp - 18};
return generated;
}
But that doesn't seem like it would generate random enough numbers (and it only spits开发者_C百科 out 0
. I', not sure why...).
Is there any way that I could make a function which spits out a new random number each time?
Not being familiar with python, I'm going to assume that random.uniform(0, 1) spits out a random number from a uniform distribution between 0 and 1?
If so, try the following:
srand(time(NULL));
float myRand = ((float) rand( )) / RAND_MAX;
Note that your mileage may vary though - rand() is not guaranteed to be a very high quality random number source. You may get visual artifacts depending on the implementation and how you're using it. I use a Mersenne Twister random number generator in my raytracer.
EDIT: Just to be a little clearer, that's:
...
void init_program ( )
{
...
srand(time(NULL));
...
}
...
float random_uniform ( )
{
return ((float) rand( )) / RAND_MAX;
}
...
If you call both srand
and rand
at the same time, you're likely to get the same "random" number each time, because unless the time
has changed in the meantime you'll seed the generator with exactly the same seed, and hence get exactly the same first random number.
Is there a reason you're not just using rand()
, which is part of the C++ standard library? The function you refer to is part of the Single UNIX Specification, but is probably not portable...
The reason you're getting the same value over and over is because you're not seeding the random number generator, so it behaves deterministically. Use srand()
or srand48()
if you're OK with the UNIX-specific functions and need the 48-bit precision. Only call it once at the beginning of your program, and pass it time(NULL)
. Don't worry about using time()
, since you're only calling this function once, you don't need to worry about always getting the same time value.
You may also want to refer to this page about how to take the return value from rand()
and scale it to the range you want effectively:
USING THE C OR C++ rand() FUNCTION
EDIT: Go back and read the docs for erand48
again. You'll notice it returns a double in the range [0, 1). You're putting that in a long, which is probably why you're always seeing zero (the value is truncated to an integer). I also think that it's probably updating the values of the unsigned long
array for you with the current number in the sequence -- you provide the storage, it uses it to "keep track" of the sequence.
Try:
unsigned short xsubi[3] = { 0, 1, 27 };
for (int i = 0; i < 10; ++i)
{
double value = erand48(xsubi);
printf("%f\n", value);
}
Yeah- it's called std::rand()
, comes as Standard and ships in <cstdlib>
.
http://msdn.microsoft.com/en-us/library/398ax69y(v=VS.100).aspx
Might want to look into Boost.Random.
精彩评论