Python中的随机数

我在《跟老齐学Python:轻松入门》中讲述while循环的章节中,设计了一个“猜数游戏”,在那个游戏中,让计算机程序“随机”生成一个某一范围内的数字,然后玩家来猜。

这里其实暗藏着一个问题:这个游戏中产生的“随机数”是不是真的随机数。

随机数(random number),在一个我们日常都会碰到的领域非常重要:密码学。一般认为,密码学中的随机数可以分为三类(参考:随机数

  1. 伪随机数
  2. 密码学安全的伪随机数
  3. 真随机数

在密码学之外,真实的物理环境中,随机现象也是存在的。比如掷骰子,它所产生的随机数是“真随机数”。再比如量子力学中借用盖格米勒计数器计得的随机数,也是“真随机数”。再反观用计算机程序得到的随机数,应该是“伪随机数”(讨论:电脑取随机数是什么原理,是真正的随机数吗?)。

但是,本文要讨论的不是密码学中的随机数,也不是物理方式得到的“真随机数”。本文要讨论的就是如何利用Python语言得到随机数——本质是“伪随机数”。

random模块

Python标准库中有生成随机数模块,名为random——英文:随机的。

>>> import random
>>> dir(random)
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI', '_BuiltinMethodType', '_MethodType', '_Sequence', '_Set', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_acos', '_bisect', '_ceil', '_cos', '_e', '_exp', '_inst', '_itertools', '_log', '_os', '_pi', '_random', '_sha512', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', 'choice', 'choices', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'triangular', 'uniform', 'vonmisesvariate', 'weibullvariate']
复制代码

这里显示出此模块的所有函数。下面选择常用项简要介绍。本文开头所提到的“猜数游戏”,程序生成的数字就是100以内的整数,可以这样得到:

>>> import random
>>> random.randint(0, 99)
21
复制代码

提醒注意的是,要在100以内的整数中随机抽取一个数字,在random.randint(0, 99)的参数中,不能写成(0, 100),它与range(0, 100)的含义不同。random.randint中是包含所设置参数的左右边界的,而range函数不包含所设置参数的右边界。

看来randint在边界处理上有点非主流。的确是,在Python中的主流是“前包含,后不包含”。其实,就在random模块中,有一个符合主流思想的,并且能得到指定范围随机整数的函数。

>>> random.randrange(0, 99)
41
复制代码

randrangerandint的第一个不同就在于右边界的处理上,randrange的取值不会包含右边界。另外,在参数上两者也不同。randrange的完整猜数列表是randrange(start, stop=None, step=1),它其实很类似range函数。

所以,可以实现这个示例:随机生成0到100(含100)间的偶数。

>>> random.randrange(0, 101, 2)
42
复制代码

除了有能够得到随机整数的函数之外,还可以得到随机浮点数。

>>> random.random() 
0.85415370477785668
复制代码

random()返回0~1之间的一个浮点数,不包含1。

>>> random.uniform(3, 9)
7.4749157626250735
复制代码

uniform则可以得到任意范围内的随机浮点数。

在random模块中,除了生成随机数之外,还能实现随机选择。

>>> random.choice('abcdefg&#%^*f')
'd'
>>> random.choice(['跟老齐学python', '轻松入门', '数据分析', 'Django实战'])
'轻松入门'
复制代码

choice函数的参数是序列,返回从序列中随机抽取的一个元素——序列不能为空。

这就类似统计中的随机抽样一样,只不过choice只能抽样一个,要想实现随机抽样若干个,可以使用sample函数。

>>> random.sample(['跟老齐学python', '轻松入门', '数据分析', 'Django实战'], 2)
['跟老齐学python', '轻松入门']
>>> random.sample(['跟老齐学python', '轻松入门', '数据分析', 'Django实战'], 2)
['跟老齐学python', 'Django实战']
>>> random.sample(['跟老齐学python', '轻松入门', '数据分析', 'Django实战'], 2)
['轻松入门', '数据分析']
复制代码

sample的参数也是序列,但是后面增加一个数字,指明要抽样的数量。

以上几个函数,是处理随机问题比较常用的。如果观察上面的通过dir(random)得到的结果,还有很多其他函数,比如根据特定分布规律生成随机数。

>>> random.gauss(0, 1.5)
-1.0137141000649095
复制代码

不过,很多时候,我们要的不是一个符合高斯分布的数值,而是要很多,即一个数据集。所以,还要有新的工具。

Numpy中的随机数组

在Numpy中,有专门生成随机数组的函数。

>>> import numpy as np
>>> np.random.random(10)
array([0.00128955, 0.83075305, 0.92794682, 0.52672079, 0.98661054,
       0.61280641, 0.31083683, 0.61955382, 0.01303459, 0.82970689])
复制代码

np.random.random(size),此函数可以生成size个元素组成的数组,该数组中的元素是[0, 1)之间随机得到的浮点数。此外,参数还可以是一个元组。

>>> np.random.random((3, 4))
array([[0.94207491, 0.39698129, 0.55712865, 0.60492688],
       [0.85246793, 0.40186698, 0.41727144, 0.34172139],
       [0.49670112, 0.28317277, 0.05541682, 0.24823907]])
复制代码

在Numpy中,元组表示的是一个数组的形状,如上面的示例,参数为(3, 4)就意味着要生成一个3×4的二维数组,并且数组中的元素是随机地从[1, 0)之间取得的浮点数。注意:关于数组的形状和轴(本例中0轴方向3个元素、1轴方向4个元素)的有关详细描述,请参考《跟老齐学Python:数据分析》一书。

与此类似的函数还有:

  • np.random.random_sample

  • np.random.ranf

  • np.random.sample

在Numpy中,还提供了很多根据某种统计分布生成随机数的方法。例如:

>>> loc, scale = 0., 1.
>>> s = np.random.laplace(loc, scale, 1000)
>>> s[:10]
array([ 0.77332728, -0.52653062, -1.20956872, -3.10205661, -0.17381902,
       -0.73947538, -0.3925799 ,  3.98593488, -0.74348744, -1.81778326])
复制代码

如此,得到了由1000个浮点数组成的一个数组,并且这些数符合拉普拉斯分布。

可以用可视化的方式将这些数的分布展现出来。

>>> import matplotlib.pyplot as plt
>>> count, bins, ignored = plt.hist(s, 30, density=True)
>>> x = np.arange(-8., 8., .01)
>>> pdf = np.exp(-abs(x-loc)/scale)/(2.*scale)
>>> plt.plot(x, pdf)
[<matplotlib.lines.Line2D object at 0x11bf99198>]
>>> plt.show()
objc[57502]: Class FIFinderSyncExtensionHost is implemented in both /System/Library/PrivateFrameworks/FinderKit.framework/Versions/A/FinderKit (0x7fffa589e1d0) and /System/Library/PrivateFrameworks/FileProvider.framework/OverrideBundles/FinderSyncCollaborationFileProviderOverride.bundle/Contents/MacOS/FinderSyncCollaborationFileProviderOverride (0x12a6d6dc8). One of the two will be used. Which one is undefined.
复制代码

输出结果: 03-01.png

其它类似函数使用方法与上述阐述相仿,就不再赘述。更多内容请参考官方文档:docs.scipy.org/doc/numpy-1…


  • 《跟老齐学Python:轻松入门》:面向初学Python的读物,深入浅出地讲解Python3基础知识

  • 《跟老齐学Python:Django实战》:是Python在网站开发方面的书籍,以项目的方式介绍Django框架的应用方式

  • 《跟老齐学Python:数据分析》:是Python在数据分析、机器学习方面的基础读物,重点介绍Numpy、Pandas的有关知识和数据可视化的实现方法。

以上书籍,各大网店有售。相关网站:itdiffer.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值