To perform computer-based simulation we need to be able to generate random numbers. Generating random numbers following a uniform distribution are the easiest to generate and are what comes out of the standard programming language "give me a random number" function. Here's a sample Python session:
Uniform random variables are super important because they are the basis from which we generate other random variables, such as binomial, normal, exponential etc.
## Discussion
We could generate real random numbers by accessing, for example, noise on the ethernet network device but that noise might not be uniformly distributed. We typically generate pseudorandom numbers that aren't really random but look like they are. From Ross' *Simulation* book, we see a very easy recursive mechanism (recurrence relation) that generates values in $[0,1)$ using the [modulo](https://en.wikipedia.org/wiki/Modulo_operation)(remainder) operation:
That is recursive (or iterative and not *closed form*) because $x_i$ is a function of a prior value:
$x_1 = ax_0$ modulo $m$<br>
$x_2 = ax_1$ modulo $m$<br>
$x_3 = ax_2$ modulo $m$<br>
$x_4 = ax_3$ modulo $m$<br>
$...$
```
x{i+1} = a xi modulo m
```
Ross indicates that the $x_i$ values are in [0,m-1] but setting any $x_i=0$ renders all subsequent $x_i=0$, so we should avoid that. Practically speaking, then, this method returns values in (0,1).
这是递归的(或迭代的而不是*闭式*),因为`xi`是先前值的函数:
To get random numbers in [0,1) from $x_i$, we use $x_i / m$.
```
x1 = a x0 modulo m
x2 = a x1 modulo m
x3 = a x2 modulo m
x4 = a x3 modulo m
...
```
We must pick a value for $a$ and $m$ that make $x_i$ seem random. Ross suggests choosing a large prime number for $m$ that fits in our integer word size, e.g., $m = 2^{31} - 1$, and $a = 7^5 = 16807$.
Ross 表示`xi`在`[0, m-1]`中,但设置任何`xi = 0`会使所有后续`xi = 0`,所以我们应该避免这种情况。 实际上,然后,此方法返回`(0,1)`中的值。
Initially we set a value for $x_0$, called the *random seed* (it is not the first random number). Every seed leads to a different sequence of pseudorandom numbers. (In Python, you can set the seed of the standard library by using `random.seed([x])`.)
Our goal is to take that simple recursive formula and use it to generate uniform random numbers. Function `runif01()` returns a new random value *for every call*. Use $m = 2^{31} - 1$, $a = 7^5 = 16807$, and an initial seed of $x_0 = 666$.
Notice that x_i is in the global space not the runif() space.
请注意,`xi`位于全局空间而不是`runif()`空间。
```python
fromlolvizimportcallsviz
...
...
@@ -77,11 +78,9 @@ runif01()
# 0.005212361926777457
```
![svg](img/4.1_random-uniform_7_0.svg)
Let's try it out:
让我们试试它:
```python
[runif01()foriinrange(4)]
...
...
@@ -94,15 +93,9 @@ Let's try it out:
'''
```
### 练习
### Exercise
Define a new function, `runif(a,b)` that generates a random number in [a,b) instead of [0,1). Hint: We need to scale and shift a random uniform value in [0,1). Note: *You can't use random.random() or any other built-in random number generators for this lab.*
@@ -130,10 +123,9 @@ print([runif(5,6) for i in range(3)])
'''
```
### 练习
### Exercise
Define a new function, `setseed(x)`, that updates the `seed` global variable.
定义一个新函数`setseed(x)`,它更新`seed`全局变量。
```python
defsetseed(s):
...
...
@@ -141,7 +133,7 @@ def setseed(s):
...
```
This test sequence:
测试序列:
```python
setseed(501)
...
...
@@ -150,7 +142,7 @@ print runif01()
printrunif01()
```
should generate:
应该生成:
```
0.00392101099897
...
...
@@ -179,10 +171,9 @@ print([runif(5,6) for i in range(3)])
```
### Random variable density function estimate
Jumping ahead a bit, we can use the histogram plotting example from [Manipulating and Visualizing Data](data.ipynb) as a crude form of density estimation to verify that the distribution of random values is approximately uniform:
In the case of generating pseudorandom numbers, we are interested in the sequence of values generated by the recurrence relation. Now we'll turn our attention to iterative methods that loop until the recurrence relation value converges.