两个随机整数的差的绝对值的数学期望值
题目
取 0 到 100(含)之间的两个随机整数,求出它们的差的绝对值,请问这个值的数学期望值是多少?(可以模拟1000次,得到其平均值,当成其数学期望的近似值)。
思路
题目要求我们模拟 1000 次。因此,我们需要进行 1000 次循环。
随机整数
在每一个循环里,我们需要生成两个随机整数。
生成随机整数的方法是 random.randint(x,y)
,其中 $x$ 和 $y$ 表示随机整数的范围 $[x,y]$ ,要注意的是 $x$ 和 $y$ 是包括在取值范围内的。在这个题目里,我们会用 random.randint(0,100)
来取 0 到 100 之间的随机整数。
接着,我们对两个随机整数取差后,取绝对值。
绝对值的定义如下:
$$
\left | x \right | =
\begin{cases}
\hfill x & \text{if $x\geq 0$}\
-x & \text{if $x<0$}
\end{cases}
$$
当差大于等于零时,不需要理会。当差小于零时,需要将差乘以 $-1$ 。翻译为 Python 就是:
if difference < 0:
difference = difference * (-1)
平均值
可以模拟 1000 次,得到其平均值,当成其数学期望的近似值
题目希望我们得到他的平均值。平均值是这样算的:
$$
平均值 = \frac {总和}{项数} = \frac {累计每一次差的绝对值}{ 1000次} = \frac {列表总和}{列表长度}
$$
方法 1:s+=
每一个循环里,我们都将这个差 difference
累计起来,存到总和 total
里。
total += difference
最后我们把 total
除以项数即可得到平均值。
print(total/sim_rounds)
方法 2:存到列表
我们将每次循环得到的 difference
放入列表 diff_list
中。
diff_list.append(difference)
最后求平均值 sum() / len()
。其中 sum()
会返回列表里每一个项相加的总和,len()
函数则会返回列表的长度,也就是我们的项数 1000 。
print(sum(diff_list)/len(diff_list))
答案
这是使用 s+=
求和,然后得到平均值的方法:
import random
total = 0
sim_rounds = 1000
for x in range(0,sim_rounds):
num1 = random.randint(0,100)
num2 = random.randint(0,100)
difference = num1 - num2
# get absolute value
if difference < 0:
difference = difference * (-1)
# Add difference to total
total += difference
# get average
print(total/sim_rounds)
我们也可以将得到的值放入列表中,最后求平均值 sum() / len()
:
import random
total = 0
sim_rounds = 1000
diff_list = []
for x in range(0,sim_rounds):
num1 = random.randint(0,100)
num2 = random.randint(0,100)
difference = num1 - num2
# get absolute value
if difference < 0:
difference = difference * (-1)
# Add difference to total
diff_list.append(difference)
# get average
print(sum(diff_list)/len(diff_list))
0 到 1 之间的随机实数的平均值与标准差
题目
用循环得到 1000 个数:每个数是由 6 个随机实数 (0到1之间的)的平均值而得到的,将这个数 append()
到列表中。计算这 1000 个数的平均值及标准差。
思路
生成随机实数
题目要求我们模拟 1000 次。
我们需要进行 1000 次大循环,得到 1000 个数,每一个数都依赖于 6 个随机实数的平均。
每一次大循环里,进行 6 次的小循环。每一个小循环里,生成 1 个随机实数。最后在小循环结束后,得到 6 个随机实数的平均值。
因此,这个题目里我们会用到双层嵌套循环(double nested loop),结构如下:
flowchart TD
B{For 循环: 小于 1000 次吗 } -->|True| C{For 循环: 小于 6 次吗 }
C -->|True| D[生成一次随机实数] --> I[加到 average]
C -->|False| G([结束 For 循环]) --> H[average 除以 6 得到六个随机实数的平均] --> J[ append 到列表中] --> B
B ---->|False| E([结束 For 循环])
要生成一个 0 到 1 之间的随机实数,我们要使用 random.random()
。
得到 6 个随机实数的平均值的方法,正是上一题里 s+=
的方法,只不过在这题里只需要把总和除以 6 就能得出平均值。
所以,这部分是这样写的:
for y in range(sim_rounds):
average = 0
for x in range(6):
num = random.random()
average += num
average /= 6
my_list.append(average)
平均函数
接着我们需要一个计算平均的函数。
sum()
一个列表会返回列表里每一个项相加的总和;len()
一个列表则会返回列表的长度,也就是列表里元素的数量。
由于 $平均 = \frac {总和}{项数} = \frac {列表总和}{列表长度}$ ,只要 sum(列表)/len(列表)
就会得出平均值。
定义一个计算平均的函数:输入参数为列表 lst
,返回平均值。
def Average(lst):
return sum(lst) / len(lst)
标准差函数
接着,我们需要一个计算标准差的函数。
先看下平均、方差和标准差的定义。
概念 | 公式 |
---|---|
平均(Mean) $\mu$ | $\mu = \frac{1}{N}\sum_{i=1}^N x_i$ |
方差(Variance)$\sigma^2$ | $\sigma^2 = \frac{1}{N} \sum_{i=1}^N (x_i - \mu)^2$ |
标准差(Standard Deviation)$\sigma$ | $\sigma = \sqrt{\frac{1}{N} \sum_{i=1}^N (x_i - \mu)^2}$ |
输入一个列表,我们要得到标准差了。定义一个标准差函数,平均函数刚才我们已经写过了,可以调用之前的平均函数。只需要把方差和标准差的数学语言翻译成 Python 编程语言:
def Standard_deviation(lst):
mean = Average(lst)
variance = sum([((x - mean) ** 2) for x in lst]) / len(lst)
res = variance ** 0.5
return res
我们先计算平均,接着是方差,接着将方差取根号得到标准差。
值得留意的是 Python 中的幂函数表示法。在 Python 里,**
代表数学的幂函数。a ** b
会返回 $a$ 的 $b$ 次幂,即 $a^b$ 。
举些例子,当前 a
值为 4。
试下 a ** 2
,也就是 $a^2$ ,会得到结果 16。
>>> print(a ** 2)
16
试下 a ** 0.5
,也就是 $a^{0.5} = \sqrt{a}$ ,会得到结果 2。
>>> print(a ** 0.5)
2.0
答案
把思路里的三个部分结合起来,就能得出最终答案。
import random
my_list = []
sim_rounds = 1000
def Average(lst):
return sum(lst) / len(lst)
def Standard_deviation(lst):
mean = Average(lst)
variance = sum([((x - mean) ** 2) for x in lst]) / len(lst)
res = variance ** 0.5
return res
for y in range(sim_rounds):
average = 0
for x in range(6):
num = random.random()
average += num
average /= 6
my_list.append(average)
print("Average is: ", Average(my_list))
print("Standard Deviation is: ", Standard_deviation(my_list))
阶乘与组合数
题目
組合数 $C(m,n)=\frac{m!}{n!(m-n)!}$。试编写阶乘的函数及组合数的函数,并调用求出 $C(6,4)$。
思路
组合数 $C(m,n) = {m \choose n}$ 的定义为:从 $m$ 个不同元素中取出 $n$ 个元素的所有不同组合的个数。
计算组合数,可以使用公式:
$$
C(m,n)=\frac{m!}{n!(m-n)!}
$$
由此公式可以得知,只要计算出阶乘,就能得到组合数。
阶乘函数
一个阶乘(Factorial)是所有小于及等于该数的正整数的积,计作 $n!$。特别地 $0!=1$。
$$
n! = (n-1)! \times n \ 1! = 0! \times 1 = 1
\
2! = 1! \times 2
\
3! = 2! \times 3
\
4! = 3! \times 4
$$
从这个规律我们能看出:只要从 $1!=1$ 开始,自增 1,然后再乘以自己,就能得到下一个阶乘,如此类推。
因此,我们只要写一个循环,做这个步骤就能算出阶乘。
def factorial(x):
fact = 1
for i in range(1,x+1):
fact = fact * i
return fact
组合数函数
我们利用公式 $C(m,n)=\frac{m!}{n!(m-n)!}$ ,阶乘部分调用刚才写的阶乘函数即可。
def combination(m,n):
return factorial(m)/factorial(n)/factorial(m-n)
答案
import random
m = int(input("Input your m: "))
n = int(input("Input your n: "))
# Calculate factorial
def factorial(x):
fact = 1
for i in range(1,x+1):
fact = fact * i
return fact
# Calculate combination
def combination(m,n):
return factorial(m)/factorial(n)/factorial(m-n)
print("{:.0f}".format(combination(m,n)))
在代码的最后一行里,由于组合数函数里使用了除法,Python 默认结果为浮点数,e.g. 307.0
,带有小数部分。
一个组合数应该是整数。因此,我们需要对输出结果进行格式控制。
print("{:.0f}".format(combination(m,n)))
浮点数格式有很多用法:
数字 | 格式 | 输出 | 描述 |
---|---|---|---|
3.1415926 | {:.2f} |
3.14 | 前两个小数位 |
3.1415926 | {:+.2f} |
+3.14 | 前两个小数位(带正负) |
2.71828 | {:.0f} |
3 | 无小数位 |
质数判断
题目
先定义一个函数判断一个数是否是质数,主程序将 2 到 100 以内的质数 append()
到一个列表中,并看看总共有多少个质数。
思路
质数(素数)的定义是:大于 1 的自然数中,除了 1 和该数自身外,无法被其他自然数整除的数。
判断是否整除的方法可以利用取模运算符 %
返回除法的余数。当 a % b
余数为 0 时,代表 $a$ 能够被 $b$ 整除,即 $b$ 是 $a$ 的因数。在这个情况中,如果 $b$ 不是 1 和 $a$ 自身,则 $a$ 不是质数。
所以,我们做一个 for
循环,从 2 开始。在每一次循环里,我们都通过取模来验证是否质数。
if (x % i) == 0:
return False
循环的范围只需要从 $2$ 到 $n/2$ ,而不需要到 $n$ 。如果一个数能被 $[2,\frac{n}{2}]$ 内的数字整除,这个数就不是质数。
for i in range(2, int(x/2)+1):
# If num is divisible by any number between 2 and n / 2, it is not prime
if (x % i) == 0:
return False
循环体本身的范围,是 int(n/2) + 1
。
int(n/2)
防止 $n$ 不被 2 整除而出现小数位的情况。
+1
加一保证第 int(n/2)
个数也会被测试到。一个 range()
函数是不包含最后一个数的。
for i in range(2, 5):
print(i) # 2, 3, 4
比如,上面这段代码的输出是 2,3,4
,不包含 5 。要遍历到最后一个数,需要加一 +1
:
for i in range(2, 5+1):
print(i) # 2, 3, 4, 5
答案
# Calculate factorial
def isPrime(x):
# Iterate from 2 to n / 2
for i in range(2, int(x/2)+1):
# If num is divisible by any number between 2 and n / 2, it is not prime
if (x % i) == 0:
return False
else:
return True
stop = 100
primeNumbers = []
for x in range(2,stop+1): # [2,100]
if isPrime(x):
primeNumbers.append(x)
print("List of prime numbers: ",primeNumbers)
print("Number of prime numbers: ",len(primeNumbers))