Python 随机性的多种用途
计算机随机数生成器(RNGs)有很多用途. 最近在教授一次程序课时,我演示了随机数的一种用法,本来我觉得这是很普遍的一种用法,结果居然有一位参与者对这种用法表示很惊奇. 这件事情使得我意识到,对于许多初学者,甚至有些富有经验的程序员来说,恐怕对于随机数的很多用法都不是很熟悉。
因此我想到了写这篇博客,这里我会演示随机数的一些用法. 这里的例子使用的是 python 语言,但是其原理和概念也可以被借用于其他编程语言--只要它也能产生随机数。
注意:所有关于随机数的使用方法,都无需用到什么高深的数学知识。
让我们开始吧。
首先,从 Python 标准库中导入并查看一下随机模块包含了哪些内容
import random
dir(random)
['BPF', 'LOG4', 'NV_MAGICCONST', 'RECIP_BPF', 'Random', 'SG_MAGICCONST', 'SystemRandom', 'TWOPI', 'WichmannHill', '_BuiltinMethodType', '_MethodType', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_acos', '_ceil', '_cos', '_e', '_exp', '_hashlib', '_hexlify', '_inst', '_log', '_pi', '_random', '_sin', '_sqrt', '_test', '_test_generator', '_urandom', '_warn', 'betavariate', 'choice', 'division', 'expovariate', 'gammavariate', 'gauss', 'getrandbits', 'getstate', 'jumpahead', 'lognormvariate', 'normalvariate', 'paretovariate', 'randint', 'random', 'randrange', 'sample', 'seed', 'setstate', 'shuffle', 'triangular', 'uniform', 'vonmisesvariate', 'weibullvariate']
我们可以看到,该模块中包含了许多函数以及包括重要数学常量(例如_e 为数学常量 e,_pi 为数学常量 pi. 这两个常量也可以在 math 模块中找到,分别为 math.e 和 math.pi) 在内的其他属性。
在本篇博文中,我需要展示的是 random() 函数的一些使用方法. 该函数是 random 模块中最基础的几个函数之一. 也许在以后的博文中,我还会接着演示其他函数及其在其他领域的使用方式。
让我们来输出一下 random 函数的文档说明字符串:
print random.random.__doc__
random() -> x in the interval [0, 1).
可以看到,该函数返回一个处于半闭区间[0,1) 的随机浮点数,即随机的一个 x,满足 0.0<=x<1.0
下面是一个名为 fn_random.py 的程序,演示了 random() 函数的一些用法:
from __future__ import print_function
# fn_random.py
# A program showing various uses of the "random" function
# from the "random" module of Python's standard library.
# Author: Vasudev Ram - https://vasudevram.github.io
# Copyright 2016 Vasudev Ram
from random import random
from random import getstate, setstate
print("Ex. 1. Plain calls to random():")
print("Gives 10 random float values in the interval [0, 1).")
for i in range(10):
print(random())
print()
print("Ex. 2. Calls to random() scaled by 10:")
print("Gives 10 random float values in the interval [0, 10).")
for i in range(10):
print(10.0 * random())
print()
print("Ex. 3. Calls to random() scaled by 10 and offset by -5:")
print("Gives 10 random float values in the interval [-5, 5).")
for i in range(10):
print(10.0 * random() - 5.0)
print()
print("Ex. 4. Calls to random() scaled by 20 and offset by 40:")
print("Gives 10 random float values in the interval [40, 60).")
for i in range(10):
print(20.0 * random() + 40.0)
下面是该程序的运行输出:
python fn_random.py Ex. 1. Plain calls to random(): Gives 10 random float values in the interval [0, 1). 0.978618769308 0.429672807728 0.807873374428 0.00775248310523 0.367435959496 0.452718276649 0.15952248582 0.183989787263 0.240112681717 0.873556193781 Ex. 2. Calls to random() scaled by 10: Gives 10 random float values in the interval [0, 10). 8.66851830984 8.06203422551 6.68791916223 6.83023335837 2.28298961244 5.06491614858 9.27404238781 2.30473573581 7.62983863372 7.18179372151 Ex. 3. Calls to random() scaled by 10 and offset by -5: Gives 10 random float values in the interval [-5, 5). 4.28960887925 -1.48913007202 -0.534170376124 3.36741617894 -3.50802287142 1.46218930484 -3.37237288568 -2.49675571636 -3.56593768859 -1.49924682779 Ex. 4. Calls to random() scaled by 20 and offset by 40: Gives 10 random float values in the interval [40, 60). 56.4292882009 40.888150119 56.867782498 58.3162130934 41.642982556 40.8419833357 52.3684662857 45.3000297458 43.1515262997 52.1129658036
上面的程序演示了如何通过乘法和加法将 random() 返回的原本处于 0 到 1 之间的值,转换为其他区间的值。
注意上面程序中 4 个部分输出的值都是完全不一样的,即使将乘法和加法的运算因素算在内也是完全不同的. 例如,第二个部分输出的值并不都是第一个部分输出值的 10 倍--虽然从代码上看,第二部分与第一部分唯一不同点就在于乘以了一个 10. 产生这个结果的原因是因为,随机数是通过遍历一个很长的序列来产生的,即序列前 10 个值作为第一部分代码的输出,而后 10 个值作为第二部分代码的输出。
若我们希望四个部分所产生的随机数一样怎么办呢(不算上乘法与加法造成的差异)?例如在有些科学与统计实验中,需要不断重复同一样的数据. 一个很直观的办法就是将第一次产生的随机数保持下来,然后在之后的代码中使用保存下来的这些随机数。
但是通过模块中的 getstate() 和 setstate() 函数,我们也能实现这一点。
首先将这一行放在 Ex.1 的代码前。
state = random.getstate()
然后将下行放在 Ex.2 到 Ex.4 的代码前. Then put this line:
random.setstate(state)
然后你会很神奇的发现,四个部分的代码所生成的随机数是一样的(不算上乘法与加法造成的差异)。在以后的博文中,我还会展示随机数的其他用法,例如可以用来对字符串做一些事情,敬请期待吧。
脚注
严格来说,这些都是尾随机数(PRNGs),但是为了简便,让我们就认为是真正的随机数吧。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: Python 异常 - 原力的黑暗面
下一篇: 数据库知识点分享
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论