Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to randomly generate really small numbers?

Suppose I want to draw a random number in the range [10^-20, 0.1], how do I do that?

If I use numpy.random.uniform, I don't seem to go lower than 10^-2:

In [2]: np.random.uniform(0.1, 10**(-20))
Out[2]: 0.02506361878539856

In [3]: np.random.uniform(0.1, 10**(-20))
Out[3]: 0.04035553250149768

In [4]: np.random.uniform(0.1, 10**(-20))
Out[4]: 0.09801074888377342

In [5]: np.random.uniform(0.1, 10**(-20))
Out[5]: 0.09778150831277296

In [6]: np.random.uniform(0.1, 10**(-20))
Out[6]: 0.08486347093110456

In [7]: np.random.uniform(0.1, 10**(-20))
Out[7]: 0.04206753781952958

Alternatively I could generate an array instead like:

In [44]: fac = np.linspace(10**(-20),10**(-1),100)

In [45]: fac
Out[45]: 
array([  1.00000000e-20,   1.01010101e-03,   2.02020202e-03,
         3.03030303e-03,   4.04040404e-03,   5.05050505e-03,
         6.06060606e-03,   7.07070707e-03,   8.08080808e-03,
         9.09090909e-03,   1.01010101e-02,   1.11111111e-02,
         1.21212121e-02,   1.31313131e-02,   1.41414141e-02,
         1.51515152e-02,   1.61616162e-02,   1.71717172e-02,
         1.81818182e-02,   1.91919192e-02,   2.02020202e-02,
         2.12121212e-02,   2.22222222e-02,   2.32323232e-02,
         2.42424242e-02,   2.52525253e-02,   2.62626263e-02,
         2.72727273e-02,   2.82828283e-02,   2.92929293e-02,
         3.03030303e-02,   3.13131313e-02,   3.23232323e-02,
         3.33333333e-02,   3.43434343e-02,   3.53535354e-02,
         3.63636364e-02,   3.73737374e-02,   3.83838384e-02,
         3.93939394e-02,   4.04040404e-02,   4.14141414e-02,
         4.24242424e-02,   4.34343434e-02,   4.44444444e-02,
         4.54545455e-02,   4.64646465e-02,   4.74747475e-02,
         4.84848485e-02,   4.94949495e-02,   5.05050505e-02,
         5.15151515e-02,   5.25252525e-02,   5.35353535e-02,
         5.45454545e-02,   5.55555556e-02,   5.65656566e-02,
         5.75757576e-02,   5.85858586e-02,   5.95959596e-02,
         6.06060606e-02,   6.16161616e-02,   6.26262626e-02,
         6.36363636e-02,   6.46464646e-02,   6.56565657e-02,
         6.66666667e-02,   6.76767677e-02,   6.86868687e-02,
         6.96969697e-02,   7.07070707e-02,   7.17171717e-02,
         7.27272727e-02,   7.37373737e-02,   7.47474747e-02,
         7.57575758e-02,   7.67676768e-02,   7.77777778e-02,
         7.87878788e-02,   7.97979798e-02,   8.08080808e-02,
         8.18181818e-02,   8.28282828e-02,   8.38383838e-02,
         8.48484848e-02,   8.58585859e-02,   8.68686869e-02,
         8.78787879e-02,   8.88888889e-02,   8.98989899e-02,
         9.09090909e-02,   9.19191919e-02,   9.29292929e-02,
         9.39393939e-02,   9.49494949e-02,   9.59595960e-02,
         9.69696970e-02,   9.79797980e-02,   9.89898990e-02,
         1.00000000e-01])

and pick a random element from that array, but wanted to clarify anyway if the first option is possible since I could be probably missing something obvious.

like image 864
jkrish Avatar asked Apr 11 '17 15:04

jkrish


People also ask

How do you generate random numbers?

There are two main methods that a computer generates a random number: true random number generators (TRNGs) and pseudo-random number generators (PRNGs). The former uses some phenomenon outside the computer for its number generation, whereas the latter relies on pre-set algorithms to emulate randomness².

How do you generate a small random number in Python?

Random integer values can be generated with the randint() function. This function takes two arguments: the start and the end of the range for the generated integer values. Random integers are generated within and including the start and end of range values, specifically in the interval [start, end].

Why is 17 the most common random number?

Seventeen is: Described at MIT as 'the least random number', according to the Jargon File. This is supposedly because in a study where respondents were asked to choose a random number from 1 to 20, 17 was the most common choice. This study has been repeated a number of times.


2 Answers

You need to think closely about what you're doing. You're asking for a uniform distribution between almost 0.0 and 0.1. The average result would be 0.05. Which is exactly what you're getting. It seems you want a random distribution of the exponents.

The following might do what you want:

import random

def rnd():
    exp = random.randint(-19, -1)
    significand = 0.9 * random.random() + 0.1
    return significand * 10**exp

[rnd() for _ in range(20)]

The lowest possible value is when exp=-19 and significand=0.1 giving 0.1*10**-19 = 1**-20. And the highest possible value is when exp=-1 and significand=1.0 giving 1.0*10**-1 = 0.1.

Note: Technically, the significand can only aprach 1.0 as random() is bounded to [0.0, 1.0), i.e., including 0.0, but excluding 1.0.

Output:

[2.3038280595190108e-11,
 0.02658855644891981,
 4.104572641101877e-11,
 3.638231824527544e-19,
 6.220040206106022e-17,
 7.207472203268789e-06,
 6.244626749598619e-17,
 2.299282102612733e-18,
 0.0013251357609258432,
 3.118805901868378e-06,
 6.585606992344938e-05,
 0.005955900790586139,
 1.72779538837876e-08,
 7.556972406280229e-13,
 3.887023124444594e-15,
 0.0019965330694999488,
 1.7732147730252207e-08,
 8.920398286274208e-17,
 4.4422869312622194e-08,
 2.4815949527034027e-18]

See "scientific notation" on wikipedia for definition of significand and exponent.

like image 106
André C. Andersen Avatar answered Sep 19 '22 11:09

André C. Andersen


As per the numpy documentation:

low : float or array_like of floats, optional Lower boundary of the output interval. All values generated will be greater than or equal to low. The default value is 0.

With that in mind, decreasing the value of low will produce lower numbers

>>> np.random.uniform(0.00001, 10**(-20))
6.390804027773046e-06
like image 21
Alexander Ejbekov Avatar answered Sep 18 '22 11:09

Alexander Ejbekov