What is the most efficient and portable way to generate a random random in [0,1]
in Cython? One approach is to use INT_MAX
and rand()
from the C library:
from libc.stdlib cimport rand
cdef extern from "limits.h":
int INT_MAX
cdef float randnum = rand() / float(INT_MAX)
Is it OK to use INT_MAX
in this way? I noticed that it's quite different from the constant you get from Python's max int:
import sys
print INT_MAX
print sys.maxint
yields:
2147483647 (C max int)
9223372036854775807 (python max int)
Which is the right "normalization" number for rand()
? EDIT additionally, how can the random seed be set (e.g. seeded based on current time) if one uses the C approach of calling rand()
from libc?
The C standard says rand
returns an int
in the range 0 to RAND_MAX inclusive, so dividing it by RAND_MAX (from stdlib.h
) is the proper way to normalise it. In practice, RAND_MAX will almost always be equal to MAX_INT, but don't rely on that.
Because rand
has been part of ISO C since C89, it's guaranteed to be available everywhere, but no guarantees are made regarding the quality of its random numbers. If portability is your main concern, though, it's your best option, unless you're willing to use Python's random
module.
Python's sys.maxint
is a different concept entirely; it's just the largest positive number Python can represent in its own int type; larger ones will have to be longs. Python's ints and longs aren't particularly related to C's.
'c' stdlib rand() returns a number between 0 and RAND_MAX which is generally 32767.
Is there any reason not to use the python random() ?
Generate random integers between 0 and 9
I'm not sure if drand is a new addition but it seems to do exactly what you want while avoiding the costly division.
cdef extern from "stdlib.h":
double drand48()
void srand48(long int seedval)
cdef extern from "time.h":
long int time(int)
# srand48(time(0))
srand48(100)
# TODO: this is a seed to reproduce bugs, put to line of code above for
# production
drand48() #This gives a float in range [0,1)
I came across this idea while researching if your division method generated sufficient randomness. The source I found makes the good point that in my case I am comparing the random number to a decimal with two digits so I really only need 3 decimal points of precision. So INT_MAX is more than adequate. But, it seems like drand48 saves the cost of division so might be worth using.