python随机数
真随机(true-random)与伪随机 (pseudo-random)
宇宙中到底存不存在真正的随机,是一个值得思考的哲学问题,虽然与正在谈的技术无关,但是这个问题对于解释我们世界的构成非常重要。
假如说宇宙中不存在真随机,我们用机械的思想来思考这个世界,即所有东西都是由确定的物理规则决定的,只要知道系统的初态以及物理规律,就可以像生命游戏那样模拟系统的整个发展过程,我们受到的限制只是计算能力以及对于规则的了解程度,这个思考方式即世界的过去、现在、未来都是确定的。这样就又引发了一些社会问题,比如如果我们都认为未来是确定的,那我们还会继续努力工作吗?如果未来是确定的,那我们是不是可以把自身的错误归结为世界的物理演化规律呢?这里就会引发很多很多问题,在这里就不继续深入了。
随着量子力学的研究,我们发现这个世界可能存在真正的随机,这个随机就是由最基本的物理规律所决定的,所以另一个思考方式是整个世界系统是随机的,未来是存在不确定性的,我们有可能通过主观能动性改变自己的未来,尽管我们不是确定世界到底存不存在真正的随机,但是从社会和个人的角度,我们更愿意相信存在真正的随机。但要强调的是,人的意志在真正的物理规律面前不堪一击,绝不能靠主观意志来认识世界,只有认识和顺应规律才能更好的生存。
在哲学层面跳了一会,我们的线程切回到编程的角度,从计算机领域理解什么是真随机和伪随机。
简单的理解:
- 真随机:结果是不确定的、不可预知的
- 伪随机:结果是确定的、可预知的
在下图中将真随机数和伪随机数进行了可视化,可以看到伪随机数中存在一些规律,利用这些规律就可以进行预测。
true random | pseudo random |
计算机中的随机数是通过算法生成的,其分布有一定的规律,而且其是可以预知的,可以复现的,所以其是伪随机数。而在计算机中,控制随机数生成的叫做随机数种子,通过种子就可以复现随机的结果。
random
random是python中的一个伪随机数生成库,如果是用于安全领域的技术的话,不要使用这个库做随机数生成。
Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the
secrets
module.
使用时需要先导入 random 库:
import random
random分为随机字节、随机整数、随机实数、随机序列等几个部分,下面会结合代码进行解释
随机数生成器(random number generator)
这里主要介绍了随机数生成器的初始化,内部状态的获取和设置。
函数名称 | 功能 | 参数 |
---|---|---|
random.seed(a=None, version=2) | ||
random.getstate() | ||
random.setstate(state) |
python中 random.seed()
用来初始化随机数生成器,如果没有参数或者没有调用这个函数的话,就默认用当前系统时间作为种子来初始化随机数生成器,其他可以用于生成的参数如下:
In the future, the seed must be one of the following types: NoneType,
int
,float
,str
,bytes
, orbytearray
.
random.seed() # NoneType
random.seed(123) # int
random.seed(1.23) # float
random.seed('test') # str
random.seed(b'test') # bytes
random.seed(bytearray('test', 'utf-8')) # bytearray
然后是关于随机数生成器的状态的获取:
random.seed(123)
state = random.getstate()
print(state)
输出(实际非常多,这里省略了中间部分):
(3, (2147483648, 2876009367, 1753366361, 587391455, 3571287981, 2841166249, 3473823116, 2904574710, 4146802524, 2741122045, 783444538,
.....
,1307775084, 3508428900, 563598120, 3962693380, 1351546783, 3657472180, 512481711, 162375823, 3972024452, 1156280088, 2910736509, 685587641, 2049376995, 4000340228, 1863192767, 3173692251, 624), None)
random.getstate()
获取了当前随机数生成器的内部状态,并将其作为一个对象返回,那么就可以将这个对象设置为随机数生成器的状态来复现结果:
实验1:
random.seed(123)
state = random.getstate()
print(random.random())
print(random.random())
print(random.random())
# 第一次
0.052363598850944326
0.08718667752263232
0.4072417636703983
# 第二次
0.052363598850944326
0.08718667752263232
0.4072417636703983
# 多次的结果均相同
实验2:
random.seed(123)
state = random.getstate()
print(random.random())
random.setstate(state)
print(random.random())
random.setstate(state)
print(random.random())
# 第一次
0.052363598850944326
0.052363598850944326
0.052363598850944326
# 第二次
0.052363598850944326
0.052363598850944326
0.052363598850944326
# 多次的结果均相同
实验3:
random.seed(123)
print(random.random())
random.seed(123)
print(random.random())
random.seed(123)
print(random.random())
# 第一次
0.052363598850944326
0.052363598850944326
0.052363598850944326
# 第二次
0.052363598850944326
0.052363598850944326
0.052363598850944326
# 多次的结果均相同
这里如何解释?重置状态和重新初始化有什么关系?
- 种子确定后,后面生成多个数,数之间不同,但每次执行的结果相同。
- 如果重置状态(刚初始化后的状态),或者重新初始化种子,会重新开始生成,所以每个数都相同
- 可以保存中间状态,重置状态后从中间开始生成
随机字节(bytes)
python3.9
print(random.randbytes(2))
随机整数(integers)
随机整数有以下几个方法
函数名称 | 功能 | 参数 |
---|---|---|
random.randrange(stop) | ||
random.randrange(start, stop[, step]) | ||
random.randint(a, b) | ||
random.getrandbits(k) |
print(random.randrange(10))
print(random.randrange(0,12,2))
print(random.randint(0,6))
print(random.getrandbits(1)) # 指定位数的整数随机数
随机序列(sequences)
函数名称 | 功能 | 参数 |
---|---|---|
random.choice(seq) | ||
random.choices(population, weights=None, *, cum_weights=None, k=1) | ||
random.shuffle(x[, random]) | ||
random.sample(population, k, *, counts=None) |
# 从序列中随机选取一个
choice_test = ['a','b','c','d']
print(random.choice(choice_test))
# 随机生成一个序列,元素可重复,可以给每个元素的可能性赋权重
choices_test = ['a','b','c','d']
print(random.choices(choices_test,weights=[100, 1, 1, 100],k=2))
# 打乱序列
shuffle_test = ['a','b','c','d']
random.shuffle(shuffle_test) # 返回值为None,直接修改原序列
print(shuffle_test)
# 随即选取序列的一个子序列,元素不重复
sample_test = ['a','b','c','d']
print(random.sample(sample_test,2)) # 返回值为子序列
随机浮点数(floats)
实数分布(Real-valued distributions)
函数名称 | 数值范围 | 分布 | 参数 |
---|---|---|---|
random.random() | [0,1) | random | |
random.uniform(a, b) | [a,b] | random | |
random.triangular(low, high, mode) | [low,high] | symmetric distribution | |
random.betavariate(alpha, beta) | [0,1] | Beta distribution | |
random.expovariate(lambd) | Exponential distribution | ||
random.gammavariate(alpha, beta) | Gamma distribution | ||
random.gauss(mu, sigma) | Gaussian distribution | ||
random.lognormvariate(mu, sigma) | Log normal distribution | ||
random.normalvariate(mu, sigma) | Normal distribution | ||
random.vonmisesvariate(mu, kappa) | Vonmi distribution | ||
random.paretovariate(alpha) | Pareto distribution | ||
random.weibullvariate(alpha, beta) | Weibull distribution |
print(random.random())
print(random.uniform(a=0,b=6))
print(random.triangular(low=0,high=10,mode=5))
print(random.betavariate(alpha=1,beta=5))
print(random.expovariate(lambd=2))
print(random.gammavariate(alpha=1,beta=2))
print(random.gauss(mu=1,sigma=0.6))
print(random.lognormvariate(mu=1,sigma=0.6))
print(random.normalvariate(mu=1,sigma=0.6))
print(random.vonmisesvariate(mu=1,kappa=0.6))
print(random.paretovariate(alpha=1))
print(random.weibullvariate(alpha=1,beta=0.6))
参考博客
http://docs.python.org/library/random.html
随机数:真随机数和伪随机数_Eyoru的博客-CSDN博客_伪随机数