[SciPy-user] random number

Robert Kern rkern at ucsd.edu
Tue Jun 29 16:34:32 CDT 2004


Steve Schmerler wrote:

[snip]

[Gary Pajer:]
>>I was going to suggest random()*1e39,   but it seems that that is not 
>>really what you want.
> 
> 
> Yes. The problem is that the minimal random numbers are mostly only 1e1
> smaller (1e199) than the max value (1e200 in my case).

In [9]: a = stats.uniform.rvs(0,1e200,size=1000)

In [10]: min(a)
Out[10]: 8.4753666305914514e+196

In [11]: max(a)
Out[11]: 9.9870741367340092e+199

Works as expected for me.

>>A uniformly distributed collection of numbers between (0, 1e38) is going 
>>to have very few members between (0, 1e3).   Or  (0, 1e24).   Or (0, 
>>1e35).    Only 1 in 10 will be in the range (0, 1e37).    It sounds like 
>>you may be looking for logarithmically distributed numbers.
>>
>>How about 10**x  where x is a random number in (0, 38).
>>
> 
> 
> Yeah, I tried something similar:
> 
>     import random
>     from Numeric import *
>     def alloverRand(min, max):
>         # e.g. max = x*10**y = exp(max_exponent)
>         max_exponent = log(max)
>         return exp(random.uniform(.1*max_exponent,max_exponent))        
> 
> This gives log-like distribution. Though it's not uniformly I'll test if it
> works since it covers _all_ numbers from (nearly 0) to 'max'.

Getting pseudo-random numbers over such a large range leaves gaping 
holes no matter what you do. Double precision will only get you 1e16ish 
possible numbers. Uniform rvs just spreads out the holes mostly evenly 
across the whole range. The exponential distribution puts those holes 
mostly out near the large end. If you want the orders of magnitude to be 
distributed evenly, then that's what you'd use. If you want the values 
themselves to be distributed evenly, then you will have to live with the 
fact that, with a perfect RNG, the probabilities of generating small 
numbers like 1e23, 1e45, and 1e2 from a range of 1e200 in your lifetime 
are too small. With a finite precision PRNG, most orders of magnitude 
are impossible to achieve:

In [19]: machar_double.epsilon * 1e200
Out[19]: 2.220446049250313e+184

The smallest exponent you can expect is 184.

So I guess my question is, "Can you do anything to reduce the range to 
something reasonable?"

-- 
Robert Kern
rkern at ucsd.edu

"In the fields of hell where the grass grows high
  Are the graves of dreams allowed to die."
   -- Richard Harter



More information about the SciPy-user mailing list