python随机数

发布时间 2023-05-08 16:16:13作者: 张好动

真随机(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, or bytearray.

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

python 随机数_utopia的专栏-CSDN博客

随机数:真随机数和伪随机数_Eyoru的博客-CSDN博客_伪随机数

python random随机数、numpy.random随机数 - 知乎 (zhihu.com)

随机数大家都会用,但是你知道生成随机数的算法吗? - 知乎 (zhihu.com)