# The NumPy random package 

## Overview
1. Introduction to Numpy.Random
2. Simple Random Data
    - Rand()
    - Randn()
    - Random_sample()
    - Choice()
    - Bytes()
3. Permutations
    - shuffle()
    - permutation()
4. Distributions
    - Uniform()
    - Normal()
    - Binomial()
    - Poisson()
5. Random Generator
6. References


## Introduction to Numpy.random
**Numpy[1]** is a package in the Python Language.  It provides a high-performance multidimensional array object, and tools for working with these arrays. It contains useful linear algebra, Fourier transform, and random number capabilities.
Numpy.random is a sub-package of the Numpy package, and it basically churns out (pseudo) random numbers, using various tools and functions. It takes advantage of the **Mersenne Twister[2]** , which is the most used pseudorandom number generator (PRNG), and is already embedded in Python's library. The functions in the numpy.random sub-package can be divided into 4 categories, which are Simple random data (getting random numbers), permutations, distributions and seeding.

## Simple Random Data

### Rand()

**Numpy.random.rand()[3]** is a function when called (with no argument), will return a random number in the **half-open interval[4]** between 0 (inclusive) and 1 (exclusive). It will also create an array of a given shape and populates it with random samples if parameters are passed through. This function uses the uniform distribution (see numpy.random.uniform).

Parameters:	
d0, d1, …, dn : int, optional
<br>The dimensions of the returned array, should all be positive. If no argument is given a single Python float is returned.

Returns:	
out : ndarray, shape (d0, d1, ..., dn)
<br>Random values.


```python
import numpy as np
np.random.rand() #produces a random float number between 0 and 1
```




    0.0923385947687978




```python
np.random.rand(2,2) #produces a 2d array with 2 rows and 2 columns
```




    array([[0.18626021, 0.34556073],
           [0.39676747, 0.53881673]])




```python
np.random.rand(3,2,2) #produces a 3d array with 2 rows and 2 columns, and a depth of 3
```




    array([[[0.41919451, 0.6852195 ],
            [0.20445225, 0.87811744]],
    
           [[0.02738759, 0.67046751],
            [0.4173048 , 0.55868983]],
    
           [[0.14038694, 0.19810149],
            [0.80074457, 0.96826158]]])



To prove that this function uses the uniform distribution, we will generate an array with 10000 values and plot it on a histogram with **matplotlib.pyplot[5]**, a useful tool for plotting data in graph form. In the graph below, we can see that the values that an almost equal number of values are generated per column.


```python
import numpy as np
import matplotlib.pyplot as plt

x = np.random.rand(10000) #generate an array with 10000 values
plt.hist(x,color='g') #plot out a histogram of the array
```

### Randn()

**Numpy.random.randn()[6]** is a function that returns a sample (or samples) from the “standard normal” distribution. Returns a random number from using the univariate “normal” (Gaussian) distribution of mean 0 and variance 1.

The normal curve (also known as the bell curve) has its symmetry about the centre. Half of the values generated will be less than the mean, and the other 50% of the values will be greater than the mean.

Parameters:	
d0, d1, …, dn : int, optional
<br>The dimensions of the returned array, should be all positive. If no argument is given a single Python float is returned.

Returns:	
Z : ndarray or float
<br>A (d0, d1, ..., dn)-shaped array of floating-point samples from the standard normal distribution, or a single such float if no parameters were supplied.


```python
np.random.randn() #returns sample with one number
```




    -0.2959569528837944




```python
np.random.randn(2,2) #returns 2 by 2 array sample
```




    array([[ 0.65228253, -0.16824741],
           [-1.3086617 , -0.82948031]])



For random samples from N(mu, sigma^2), use:

sigma * np.random.randn(...) + mu

Two-by-two array of samples from N(2, 6.25):


```python
2.5 * np.random.randn(2, 2) + 2  #returns 2 by 2 array sample N(2, 6.25)
```




    array([[ 6.33697059,  5.7842766 ],
           [ 1.69177013, -1.772594  ]])



Sample of 10000 values using this function will display a bell curve:


```python
x = np.random.randn(10000) #generate an array with 10000 values
plt.hist(x,color='r')
plt.show()
```

Further explanation of the normal distribution explained under numpy.random.normal()

### Randint()

**numpy.random.randint()[7]** is a function that returns random integers from low (inclusive) to high (exclusive). It uses the discrete uniform distribution, similar to the numpy.random.rand function. 

Parameters:	
low : int
<br>Lowest (signed) integer to be drawn from the distribution (unless high=None, in which case this parameter is one above the highest such integer).

high : int, optional
<br>If provided, one above the largest (signed) integer to be drawn from the distribution (see above for behavior if high=None).

size : int or tuple of ints, optional
<br>Output shape. If the given shape is, e.g., (m, n, k), then m * n * k samples are drawn. Default is None, in which case a single value is returned.

dtype : dtype, optional
<br>Desired dtype of the result. All dtypes are determined by their name, i.e., ‘int64’, ‘int’, etc, so byteorder is not available and a specific precision may have different C types depending on the platform. The default value is ‘np.int’.

Returns:	
out : int or ndarray of ints
<br>size-shaped array of random integers from the appropriate distribution, or a single such random int if size not provided.

note: random.random_integers, which is similar to this function, has been deprecated.

Example: Coin flip example, possible integers are 0 (heads) or 1 (tails)


```python
np.random.randint(2) #random number is either 0 or 1
```




    0



Example: Generate a random byte


```python
np.random.randint(2, size = 8)
```




    array([0, 1, 1, 1, 1, 0, 0, 0])



Example: Generate a sample with 10 numbers of which numbers are between 2(inclusive) and 5 (exclusive)


```python
np.random.randint(2,5,size=10) 
```




    array([2, 2, 3, 4, 2, 2, 4, 4, 3, 2])



Example: Generate a sample with 10 by 5 numbers that are between 2(inclusive) and 5(exclusive)


```python
np.random.randint(2,5,size=(10,5))
```




    array([[2, 3, 2, 4, 3],
           [2, 3, 3, 2, 4],
           [3, 3, 2, 4, 4],
           [2, 4, 4, 2, 3],
           [3, 2, 3, 4, 4],
           [3, 2, 4, 3, 4],
           [2, 3, 2, 4, 4],
           [4, 2, 2, 3, 4],
           [3, 4, 4, 4, 4],
           [2, 3, 4, 3, 2]])



### Random_sample()

**numpy.random.random_sample()[8]** is a function that returns random floats in the half-open interval. Similar to the randint() function, but instead of returning ints, it'll return floats. Calling a function without any parameters will output a float between 0.0(inlusive) and 1.0(exlusive). Results are based off the continuous uniform distribution.

Parameters:	
size : int or tuple of ints, optional
<br>Output shape. If the given shape is, e.g., (m, n, k), then m * n * k samples are drawn. Default is None, in which case a single value is returned.

Returns:	
out : float or ndarray of floats
<br>Array of random floats of shape size (unless size=None, in which case a single float is returned).



Example: Generate a random price for a good under one euro


```python
round(np.random.random_sample(),2) #gets a random float and round up to two decimal places
```




    0.1



Example: Generate an array of 3 random floats


```python
np.random.random_sample(3)
```




    array([0.947187  , 0.47447803, 0.63588946])



Example: Generate a random float between -5 and 15
Use formula : (b - a) * random_sample() + a


```python
(15 - -5) * np.random.random_sample() + -5
```




    -4.464749887084832



Example: Return a 3 by 3 array of random floats between -5 and 15


```python
(15 - -5) * np.random.random_sample((3,3)) + -5
```




    array([[ 6.34331272, 13.16863128,  8.17594392],
           [12.99294443, -0.53621199,  3.77536419],
           [11.48817683,  5.83157003,  1.45544615]])



*random(),ranf(), and sample() functions are similar to random_sample and have been deprecated

### Choice()

**numpy.random.choice()[9]** function generates a random sample from a given 1-D array. It uses a uniform distribution when generating the sample, or a non-uniform sample if the user specifies the probability of each element in the array.

Parameters:	
a : 1-D array-like or int
<br>If an ndarray, a random sample is generated from its elements. If an int, the random sample is generated as if a were np.arange(a)

size : int or tuple of ints, optional
<br>Output shape. If the given shape is, e.g., (m, n, k), then m * n * k samples are drawn. Default is None, in which case a single value is returned.

replace : boolean, optional
<br>Whether the sample is with or without replacement

p : 1-D array-like, optional
<br>The probabilities associated with each entry in a. If not given the sample assumes a uniform distribution over all entries in a.

Returns:	
samples : single item or ndarray
<br>The generated random samples

Raises:	
ValueError
<br>If a is an int and less than zero, if a or p are not 1-dimensional, if a is an array-like of size 0, if p is not a vector of probabilities, if a and p have different lengths, or if replace=False and the sample size is greater than the population size

Example: Generate a uniform random sample from an array of number [0,1,2,3,4] of size 4.


```python
np.random.choice(5, 3)
```




    array([2, 1, 4])



Example: Generate a non-uniform random sample from an array of numbers [0,1,2,3,4] of size 4.


```python
np.random.choice(5, 3, p=[0.1, 0.1, 0.1, 0.7, 0])
```




    array([3, 3, 2], dtype=int64)



Example: Generate a uniform random sample from np.arange(5) of size 3 without replacement:


```python
np.random.choice(5, 3, replace=False)
```




    array([1, 3, 2])



Example: Prove that the non-uniform random sample generated uses the probability given to each element. Create a sample size of 1000 with fruit elements, with varying probabilities. The total number of times per fruit is generated should match up to the probabilities given to the respective fruit.


```python
x = np.random.choice(["apple","banana","orange","berry"],(1000),p=[0.1,0.1,0.2,0.6])
plt.hist(x,color='b')
```

As we can see from the graph, berries was given a probability of 0.6, and hence roughly 600 berry objects were created out of a sample size of 1000.

### Bytes()

numpy.random.bytes() is function that generates random bytes.
Parameters:	
length : int
<br>Number of random bytes.

Returns:	
out : str
<br>String of length length.

Example: Generate a random bte with length 5 and convert to string.


```python
x = np.random.bytes(5)
"".join(map(chr, x))
```




    '[\tv\xa0×'



## Permutations

### Shuffle()

**shuffle[11]** is a function that modifies a sequence by shuffling its contents. For multi dimentionally arrays, shuffle() will only change the order of the array along the first axis.

Parameters:	
x : array_like
<br>The array or list to be shuffled.

Returns:	
<br>None

Example: Shuffle an array of integers:


```python
arr = np.arange(10)
np.random.shuffle(arr)
arr
```




    array([8, 4, 9, 5, 1, 3, 7, 6, 0, 2])



Example: Shuffle the order of a 2d 3 by 3 array along the first axis.


```python
arr = np.arange(9).reshape((3, 3))
np.random.shuffle(arr)
arr
```




    array([[6, 7, 8],
           [0, 1, 2],
           [3, 4, 5]])



### Permutation()

permutation()[12] is a function that takes in an array and returns a permutated copy of that array. For multi dimentionally arrays, shuffle() will only change the order of the array along the first axis.


Parameters:	
x : int or array_like
<br>If x is an integer, randomly permute np.arange(x). If x is an array, make a copy and shuffle the elements randomly.

Returns:	
out : ndarray
<br>Permuted sequence or array range.

Example: Permutate an array of 10 integers from 0-9


```python
np.random.permutation(10)
```




    array([2, 7, 1, 9, 0, 5, 8, 6, 4, 3])




```python
arr = np.arange(9).reshape((3, 3))
print("permutated array:")
print(np.random.permutation(arr))
print("original array (not changed):")
print(arr)
```

    permutated array:
    [[0 1 2]
     [3 4 5]
     [6 7 8]]
    original array (not changed):
    [[0 1 2]
     [3 4 5]
     [6 7 8]]


*The **difference[13]** between shuffle() and permutation() is that for permutation(), a copy of the array is shuffled, where as the array itself is shuffled for shuffle() 

## Distributions

### Uniform()
**Numpy.random.uniform()[14]** is a function that draws samples from a uniform distribution. Samples are uniformly distributed over the half-open interval [low, high) (includes low, but excludes high). It is the default distribution function used by rand(), randint() and random_sample()

The probability density function of the uniform distribution is
$$p(x) = \frac{1}{b - a}$$
where a = low and b = high

For example: if a = -5 and b = 5
$$p(x) = \frac{1}{5 -(-5)} = \frac{1}{10}$$
therefore, the probability of every object in that array is 0.1

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

high : float or array_like of floats
<br>Upper boundary of the output interval. All values generated will be less than high. The default value is 1.0.

size : int or tuple of ints, optional
<br>Output shape. If the given shape is, e.g., (m, n, k), then m * n * k samples are drawn. If size is None (default), a single value is returned if low and high are both scalars. Otherwise, np.broadcast(low, high).size samples are drawn.

Returns:	
out : ndarray or scalar
<br>Drawn samples from the parameterized uniform distribution.

Example: Generate a random sample that is uniformly distributed with 10000 values from 0 to 10


```python
import matplotlib.pyplot as plt
s = np.random.uniform(0,10,10000)
count, bins, ignored = plt.hist(s, 10, density=True, color='g')
plt.axhline(y=np.average(count), color='r', linestyle='-')
plt.show()


```

Based on that diagram, we can see that the graph shows a fairly uniform result. The red line shows the probability p(x) of this distribution, which is at 0.1. There is little fluctutation in between the columns. 

### Normal()

The **numpy.random.normal()[15]** function draws random samples from a normal distribution. It is also known as the bell curve because of its shape. 

Parameters:	
loc : float or array_like of floats
<br>Mean (“centre”) of the distribution.

scale : float or array_like of floats
<br>Standard deviation (spread or “width”) of the distribution.

size : int or tuple of ints, optional
<br>Output shape.

Returns:	
out : ndarray or scalar
<br>Drawn samples from the parameterized normal distribution.

Data can be "distributed" in different ways, but in many cases, data tends to be around a central value with no bias left or right, and it gets close to a normal distribution like this[16]: 

50% of values less than the mean and 50% greater than the mean, and the symmetry is about the center. 

To understand normal distributions, we need to understand what **standard deviations** are. Standard deviations is basically a measure of how spread out numbers are. When we calculate the standard deviation we find that generally:
1. 68% of values are within 1 standard deviation of the mean
2. 95% of values are within 2 standard deviations of the mean
3. 99.7% of values are within 3 standard deviations of the mean

Example of drawing a bellcurve of the height of students in a school, with mean 1.4, standard deviation of 0.15 and a sample size of 1000 students. [17]


```python
s = np.random.normal(1.4, 0.15, 1000)
count, bins, ignored = plt.hist(s, 30, density=True,alpha=0.5)

import matplotlib.mlab as mlab
y = mlab.normpdf(bins, 1.4, 0.15) # add the best fit line
plt.plot(bins, y, 'r--')
plt.subplots_adjust(left=0.15)
plt.axvline(x=1.4, color='y')
plt.axvline(x=1.25, color='y')
plt.axvline(x=1.1, color='y')
plt.axvline(x=1.55, color='y')
plt.axvline(x=1.7, color='y')
```

### Binomial()

The **numpy.random.binomial()[18]** function draws samples from a binomial distribution.


Parameters:	
n : int or array_like of ints
<br>Parameter of the distribution, >= 0. Floats are also accepted, but they will be truncated to integers.

p : float or array_like of floats
<br>Parameter of the distribution, >= 0 and <=1.

size : int or tuple of ints, optional
<br>Output shape. 

Returns:	
out : ndarray or scalar
<br>Drawn samples from the parameterized binomial distribution, where each sample is equal to the number of successes over the n trials.

Example: Tossing a coin. The probability of the coin landing on heads is 0.5, and the probability of the coin landing on tails is also 0.5. If the coin is tossed 3 times, what are the probabilities of every outcome?

There are 8 possibilities:
1. HHH
2. HTT
3. HHT
4. HTH
5. THT
6. TTH
7. THH
8. TTT

Therefore, we can see that the probability of getting 3 heads is 1/8 (HHH), the probability of getting 2 heads is 3/8 (HHT,HTH,THH), the probability of getting 1 head is 3/8 (THT,TTH,HTT), and the probability of getting no heads is 1/8 (TTT). 

Let's run this test 100 times using numpy:


```python
n, p = 3, 0.5
x = np.random.binomial(n, p,100)
plt.hist(x)
```

From the graph, we can see roughly 3/8 or 38 times there will be two heads or two tails, and 1/8 of the time, there will be no tails or no heads.

Example: Dangerous Road. Unlike a coin flip with has an equal probability, the probability of an accident occuring on a dangerous road might not be equal as not having an accident. Say if the chances of having an accident on this road is 0.3 (0.7 probability of a safe journey), what is the probability that the next 5 out of 10 cars will be involved in an accident?

Let's run this test 10000 times:


```python
n, p = 10, 0.3

x = np.random.binomial(n, p,10000)
plt.hist(x)
```

We can see that roughly 1000 times out of 10000 times the next 5 cars will be in accidents, that means the probability of the next 5 cars being in an accident is 10%.

Examples referenced from **mathisfun.com[19]**

### poisson()

The **numpy.random.poisson()[20]** function draws samples from a poisson distribution.

Parameters:	
lam : float or array_like of floats
<br>Expectation of interval, should be >= 0. A sequence of expectation intervals must be broadcastable over the requested size.

size : int or tuple of ints, optional
<br>Output shape. 

Returns:	
out : ndarray or scalar
<br>Drawn samples from the parameterized Poisson distribution.



Above shows an example of Poisson curves with carying lamdas, extracted from the **umass maths department website[20]**. The Poisson distribution shows that the smaller the lambda, the range of likely possibilities will lie closer to the zero line.  For example, if the lambda is 1, the graph will be skewed to the left, compared to say lambda = 5 where the graph will be less skewed.

The values of a poisson curve can be calculated using the Poisson distribution formula, which is <br>
$$P(k; \lambda)=\frac{\lambda^k e^{-\lambda}}{k!}$$

Example: In the World Cup, an average of 2.5 goals are scored each game. Modeling this situation with a Poisson distribution, what is the probability that  goals are scored in a game? (example from brilliant.org[21]


\begin{align}
P(X=0)= \frac{2.5^0e^{-2.5}}{0!} \approx 0.082\\\\
P(X=1) = \frac{2.5^1e^{-2.5}}{1!} \approx 0.205\\\\
P(X=2) = \frac{2.5^2e^{-2.5}}{2!} \approx 0.257\\\\
P(X=3) = \frac{2.5^3e^{-2.5}}{3!} \approx 0.213\\\\
P(X=4) = \frac{2.5^4e^{-2.5}}{4!} \approx 0.133\\\\
\vdots
\end{align}



```python
s = np.random.poisson(2.5, 10000)
count, bins, ignored = plt.hist(s, 10, density=True, color="purple")
plt.show()


```

## Random generator

As mentioned above, numpy uses the Mersenne Twister for its PseudoRandom Number Generator (PRNG).  The PRNG-generated sequence is not truly random, because it is completely determined by an initial value, called the PRNG's seed (which may include truly random values). 

The functions included in numpys random generator are:
1. **numpy.random.RandomState()[23]**, a container for the Mersenne Twister pseudo-random number generator.
2. **numpy.random.seed()[24]**, which seeds the generator
3. **numpy.random.get_state()[25]**, which returns a tuple representing the internal state of the generator.
4. **numpy.random.set_state(state)[26]**, which sets the internal state of the generator from a tuple.

An example of seeding and containing random states, from this **stackoverflow explanation[27]**:

When a user calls the function np.random.seed(1), the seed for the generator is set to the first number.




```python
np.random.seed(1)
print(np.random.rand())
print(np.random.rand(2,2))
```

    0.417022004702574
    [[7.20324493e-01 1.14374817e-04]
     [3.02332573e-01 1.46755891e-01]]


When the user runs the same two functions with the same seed, the results should be the exact same:


```python
np.random.seed(1)
print(np.random.rand())
print(np.random.rand(2,2))
```

    0.417022004702574
    [[7.20324493e-01 1.14374817e-04]
     [3.02332573e-01 1.46755891e-01]]


We can use np.random.RandomState as a container for the PRNG:


```python
r = np.random.RandomState(1)
print(r.rand())
print(r.rand(2,2))
```

    0.417022004702574
    [[7.20324493e-01 1.14374817e-04]
     [3.02332573e-01 1.46755891e-01]]


The user can run get_state() which will return the entire PRNG:


```python
print(r.get_state())
```

    ('MT19937', array([2629073562, 2983301384,  681580311, 4033622241,  792772838,
           3306961981,   92883131, 1785085746, 3364128315, 2402025379,
           3224868746, 1145213362, 3784365245, 1948434636, 2667646161,
           2598854474,  921967201, 1345782310, 4019597455, 2906395199,
           1349669984, 2676817993, 4201769589, 2002781766, 3540177092,
           4224925813, 3661313599, 1709930435, 1812273278, 2973452884,
           1592291796, 3452239013, 3588672187, 3228651068, 3191454495,
           3286135343, 2640545275, 3096953148, 3746505897, 2292163827,
           2164382601, 1581410039, 2413832827, 2536571847,  179684232,
           1638923698, 3155158821, 1454330362, 4050607484,  607322300,
           2216566078,  597866774, 1036426282,  732815996, 3131865469,
           2440339870, 2814550949, 1479383443, 2449469876, 3810238677,
           2923086221,  437801529, 2891199990, 1886893516, 3898673786,
            376204646, 1392372379, 4123661669, 1140754642, 3539167101,
           2386309702, 3740957436, 4033654965, 1720449988, 3434980330,
           4213508374, 3576835843, 2818865106, 1653162115, 2935588114,
           3870616539,  102614847, 1476834675, 1220770796, 1233652508,
           2385138085, 1300608482, 2753953039,  262993567, 4009374062,
           2143978386, 1613109469, 3072671496, 1223816410, 4088822114,
           3382188205, 2250056281, 1926821318, 3806317775, 2882166470,
             94227745, 2877123406, 1030225246, 1555072155,   95009460,
           1855512191, 2840453856, 2478087736,  836340051, 1566383306,
           2625414289, 3519123538,  840509954, 2373484829,  676528503,
           2783662465, 3557034492, 2566048980, 2347785709, 3566819907,
           1311855742,  198269976, 2693520819, 2127070362,  961491174,
           3932714317,  837664826, 4277891831, 3535515583, 2831416447,
           3505045078, 3763313683,  367436315, 3614057572, 3780746374,
           2693039652, 2297021184, 2224934154,  698822522, 2718629137,
           1175446314, 2603507610, 2067589016, 2280810156, 2037033584,
           3956938481, 1112874779, 3264939860, 2054107185, 2354026721,
           1958640221, 2844284824, 3775753525, 2462549847, 3562644229,
           3683686884, 3714884555, 2266356233, 2808583945,  980888698,
           1137581788, 2771236582, 1975939317, 1605707990,  614167064,
            767063856, 4227905160, 3590303986, 2932373212, 2230415839,
            127157074, 2328724316, 3356372094, 3215726425,  282321962,
           4226412442,  106823192, 3925701436,  610765913,  281952627,
           1832011890, 2670621135, 1012800992, 1489632964, 1371755819,
           2529629289,  607643288, 3941535311, 3202770816,  284461833,
           3696778854,  325625733, 2671656400, 1391137252, 1240723705,
           3132941411,  314202987, 1301784708, 2575857120,  313287791,
           3569720512,  981744121, 2986286440, 1051168756, 3881027887,
           1088809168, 3421075971, 2655923113, 2577977181, 3968201444,
           1406585576, 4001025594, 1854233928, 3825832114,  954907921,
           3109212504, 1706316388, 1550715292, 2934259476, 1892992132,
           4050317728, 4110743408,  359920673, 3542060425,  597068400,
            843058885, 3799566677, 2064802063,  860032883, 2732673041,
           3457529378, 3660165513, 1125914118, 4212233956, 3757086488,
           2632116865,  462233764,  161423763,  141910303, 2265109737,
           1983126147, 2231395445, 2147383559,  611750005, 2194081082,
           1699618892, 3841025952, 1294478167,  936120505, 4102008957,
           4268194620, 1994019922, 1187332833, 3953675561, 1917283619,
            896867387, 1634068959, 3950876764,  485558549,   45383166,
           2795959904, 1717914918, 3449856475, 3796449494, 3318166191,
           1007512487,  480498390, 1730605673, 3972660041, 2287008439,
            539639323, 1569683418, 3795864463,  453065119, 2449404120,
            265049099, 3514892628, 2665563904, 2534523080, 1969344934,
           4294466702, 1478959417, 1858551310, 3029422620, 4121720519,
           2933843154, 3209557296, 3111170404, 4264711934, 2448282623,
           1388503581, 1999436060,  818418468, 3283991819, 2356924521,
           2684567658, 1424193429, 1187340812, 3847120877, 1987859863,
           1879502046, 3422594099, 1419478013, 4148487199, 2538837125,
           3694851522,  636350498, 1097832595, 3779331880,  351970715,
           2534774459, 3389311029, 3762283879, 3742425828, 3882821767,
              2683353, 1981273229, 4068324016,  539226467, 2411256222,
           1780609115, 2059099269, 2889497980, 1123848930,  540086248,
           3467353606, 3362203896, 4058078927,   93044840,  426751932,
            824266620, 3444590461, 2122918776, 3339845861, 4233923286,
           3733051177, 2957657929, 3110908772, 2551930098, 1294126893,
           2213336821, 2124571119,   49780221, 2901327722, 2493306969,
           2545470627,  102527300, 3876142393, 4097726412, 3510695954,
            660912408, 2033930425, 1601509561,  969180562,  635252598,
            177954239, 3054207519, 4122051269, 2787463443, 1664731394,
           2907371963, 1484884283, 1560546623, 2902374922, 2395942225,
            451352804, 3346805556, 3459298550, 3482428591,   10753957,
           4101820340, 3306178891, 1122941824,  355877597, 1683964498,
            238724805, 3926649337, 3197046734, 4277634633, 2288745211,
           4202067531,  526022968, 4017453944, 1499184106, 2677441952,
           2227353703, 1995296581, 1690255681, 2920887680,  605849491,
           3072795503,  746910746, 2709796449, 1225135658,  657841564,
           4070363626,  144842260, 3718575695, 3159187032,   88291794,
           3129049475,  410962657, 1728726693, 2397606939, 4126386549,
            751549633, 4226219908, 1549973222, 3060733996, 3741110422,
           2530947598, 2627897488, 2317706652, 1170828427, 2671701715,
           1153351468, 3762293788, 4093330405, 1641962571,  699324101,
           3173743570, 1798831929, 3467616712, 4198420524, 2448981354,
            499920867,  968642107, 2140815539, 4193124145, 1639223168,
            284638153,  396985542, 3543438633,  237854258, 3938010494,
             24441053, 2947436871, 1273496002,  719279415, 3574242559,
           1040109604, 3849196601, 3250223302, 3411729501, 3031943234,
           2932285520, 2932420675, 2011314805, 2480850074, 3207806491,
            462404995, 3279042455, 4270524229, 1064389665, 1894847490,
            721365878,  357178131, 2827490451, 2604438657,  242514037,
            678802395, 1322770750, 2747624534, 4246466163, 4188936761,
           1207204018,  980275996,  841637218, 1468131552, 4102349079,
            586888764, 3105466755, 1628818384, 2991889790, 2801191520,
           2114916962, 1124291831, 3242113092, 1082871720, 3625937786,
           2796251125, 1651820702, 3427511545, 2035120316, 1024058911,
           4209506140, 2527167744,  213886228, 2514956543, 2450260579,
            327684603, 3444379103, 3884997363, 2844468873, 2261078634,
           3926825101,  439487268, 3789435080, 1212963762, 4259079565,
           2772611204, 2534236055, 2430244594,  916922266,  903950702,
           3381351589, 2268543712, 3616954837, 1273083041, 1682465785,
           1342921678, 2593265787, 3033724173, 2988544460, 1824668777,
           1214999983,  257453352, 4187931679, 3523379959, 1481153225,
           4290295859,  220376185, 4136013972,  511679284, 3510589272,
           1404047266, 3712771231, 2125374725,   32037606, 3601685135,
           3433623522,  841138647, 1610171318, 3920699442, 1084892922,
           3146108732, 3672652561, 1148331655, 2473777375, 3039860130,
           1170979324,  575756423, 1389255297,  339011744, 2351938991,
           4050094885, 2773634239, 3715040333, 3920910597,  562407139,
             29887881, 1623822350,  358193390, 1822261341, 1243290919,
            755541153,  153529770,  994467513, 1339524978, 3174283928,
           2782204324,  182251010, 1833692038, 3477775846, 2820237500,
           2165639585, 4089211432, 4010345846, 1238643345, 3710224584,
           2251039304, 1196168985, 3165387311, 3920626153, 1796963839,
           2112227260, 3358845388,  593715887, 3046897033, 2968478428,
           3846781604, 3565923316, 2452128692,   68338106, 1427007580,
           2192917968,   75235680, 2134869635, 1857807303, 3745016485,
           2601327385,   35512535,  559792668, 2093376088,  939608650,
           2259549051, 2605376692, 2058599240, 2980581379, 3160415220,
           2739135905,  254886981, 1652380747,  371107437, 1123937393,
           4185309254,  864314942, 2739416220, 2185572068, 1163546293,
           3491702910,  996401156, 1198755052, 2898003956,  745796080,
           4127642404, 4237523457, 1274635091, 3144139009, 1600421663,
           4226154574,  538248802,  373236455,  116925273], dtype=uint32), 10, 0, 0.0)


## References
1. https://www.numpy.org/ - Welcome to NumPy - Introduction of NumPy
2. https://www.maths.tcd.ie/~fionn/misc/mt.php - Details of the Mersenne Twister formula
3. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.randint.html#numpy.random.randint - numpy.random.rand() explanation
4. http://mathworld.wolfram.com/Half-ClosedInterval.html - explanation of the half-open interval
5. https://matplotlib.org/api/pyplot_api.html - introduction to matplotlib.pyplot package
6. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.randn.html#numpy.random.randn - numpy.random.randn() explanation
7. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.random_integers.html#numpy.random.random_integers - numpy.random.randint() explanation
8. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.random_sample.html#numpy.random.random_sample - numpy.random.random_sample explanation
9. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.choice.html#numpy.random.choice - numpy.random.choice() explanation
10. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.bytes.html#numpy.random.bytes - numpy.random.bytes explanation
11. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.shuffle.html#numpy.random.shuffle - shuffle() explanation
12. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.permutation.html - permutation() explanation
13. https://stackoverflow.com/questions/15474159/shuffle-vs-permute-numpy - difference between shuffle() and permutation()
14. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.uniform.html#numpy.random.uniform - official numpy reference for numpy.random.uniform()
15. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.normal.html#numpy.random.normal - official numpy reference for numpy.random.normal()
16. https://www.mathsisfun.com/data/standard-normal-distribution.html - good explanation of bell curves by math is fun.
17. https://plot.ly/matplotlib/histograms/#basic-histogram-with-hist-function - code to draw bell curve
18. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.binomial.html#numpy.random.binomial - official numpy reference for numpy.random.binomial()
19. https://www.mathsisfun.com/data/binomial-distribution.html - good examples of binomial distribution
20. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.poisson.html#numpy.random.poisson - official numpy reference for numpy.random.possion()
21. https://www.umass.edu/wsp/resources/poisson/ - good explanation and graphs for poisson curve
22. https://brilliant.org/wiki/poisson-distribution/ - good examples of poisson curve
23. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.RandomState.html#numpy.random.RandomState - official numpy reference for numpy.random.RandomState()
24. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.seed.html#numpy.random.seed
25. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.get_state.html#numpy.random.get_state
26. https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.set_state.html#numpy.random.set_state
27. https://stackoverflow.com/questions/22994423/difference-between-np-random-seed-and-np-random-randomstate?rq=1


```python

```

80abea75aa667289f1d25a3f84df33ca05d8b4d2
ipynb
Jupyter Notebook
numpy-random.ipynb
yonjeremy/emerging-technologies-assesment
4afbad9af44e865a551e7e1c2e820721cb304fce
MIT
numpy-random.ipynb
yonjeremy/emerging-technologies-assesment
4afbad9af44e865a551e7e1c2e820721cb304fce
MIT
numpy-random.ipynb
yonjeremy/emerging-technologies-assesment
4afbad9af44e865a551e7e1c2e820721cb304fce
MIT
Qwen/Qwen-72B
1. YES
2. YES