关于随机数

简介:

在使用计算机的过程中,有很多情况会接触到随机数。比如,播放器的随机播放、游戏中的随机事件、等等。尽管这些东西都号称随机,但是用户体验总是会出些问题。比如,选择了随机播放,放来放去却总是那几首歌。又比如,游戏中的随机事件,总能被有经验的玩家猜中七八成。这是怎么回事呢?

这个问题可能牵扯到的范围实在太大了:程序是否实现了随机?人的经验产生了多大作用?……甚至于,宇宙中是否存在随机?(如果宇宙中的一切都是由物质构成的,并且物质的运动遵循固定的规律,那么宇宙中一切事物的发展轨迹就已经注定了。这就是所谓的“宿命论”。)

就我目前的理解而言,只能用“伪随机”来解释这个问题:计算机产生的随机数并不是真正的随机数。

在计算机中,经典的随机数产生算法是给定一个函数y=f(x),每个随机数都是通过它进行一次迭代而产生的。函数f(x)的迭代过程如下:
x0, x1=f(x0), x2=f(x1), ..., xn=f(xn-1), ...
第0个随机数x0被称为种子。

在标准C中,提供函数srand()用于设置种子、rand()用于进行一次迭代,产生一个随机数。

很显然,在种子确定、迭代函数确定的情况下,迭代序列中的每一个xn都是确定的。这种算法完全不存在随机性。但是,这样的算法为什么能够用于生成随机数呢?

通过某个函数式进行迭代,当迭代次数充分大时,迭代序列可能有几种结果:
1、收敛;
2、出现周期性重复;
3、没有规律、杂乱无章,称之为混沌;

而随机数算法所需要的就是“混沌”这个结果,为此,迭代函数是精心选择的。这时候,迭代序列中的每一个xn杂乱无章地分布在某一区间中。在没有人知道迭代函数的情况下,姑且可以认为迭代序列是随机的。

可见,随机函数生成的随机数与真正的随机还是有很大差别的。

在C中,每次执行程序时,rand()都会生成相同的随机数序列。所以,一定要通过srand()来设置不同的种子。
有人认为,尽管随机数生成算法是“伪随机”的,但是我们可以给它设置一个随机的种子,使它产生的随机数真正随机。
但是这显然是不对的,种子和迭代函数都已经确定了,今后将要产生的数数也都已经注定了。这样的数据能称得上随机吗?
所以,通过一些客观因素(比如时间)来设置种子,可以提升随机数生成函数的表现,但是并不能改变它“伪随机”的本质。

那么,计算机能不能产生真正的随机数呢?其实,linux上有个叫/dev/random的文件,就能做到真正的随机。

/dev/random是linux内核创建的一个设备文件,每次读取这个文件,内核会输出一个随机串。
这个随机串从哪里来呢?其来源主要是外设中断。有这样一些外部设备,它们产生的中断是随机的。比如网卡,它接收到数据而产生中断的时刻基本上就是随机的。哪怕你刻意在某一时刻向网卡发送一个报文,网卡产生中断的时刻也是很不确定的。因为报文在传输过程中将受到传输介质的影响、网卡可能先收到了别人发送的报文、网卡收到报文后也不确定要等待多少时间CPU才进入中断(中断是不能中断正在执行的指令的)。所以,除非是刻意制造的实验环境,否则可以认为这一类外设能够提供随机的数据。

这些随机数据被称为“熵”,内核它们存储在“熵”池中。它在每次有新数据进入时,内核还需要做一些处理,取出数据中真正随机的那一部分(比如以网卡中断的时间为随机数据,那么“年月日”等信息显然不是随机的),然后进行一些数学变换,以便保存和输出。

实际使用中可能出现“熵”供小于求的情况,那么读/dev/random时,熵池为空,进程就要被阻塞,以等待下一个熵。于是内核又提供了另外一个文件/dev/urandom,作为折衷,如果熵池已经读空了,则产生伪随机数。

但是,从目前常用的这些软件来看,使用真随机的估计并不多。


目录
相关文章
|
人工智能 数据安全/隐私保护
AIGC作品的版权归谁
【2月更文挑战第13天】AIGC作品的版权归谁
382 1
AIGC作品的版权归谁
|
编解码 openCL TensorFlow
RK3568开发笔记(一):瑞芯微RK3568芯片介绍,入手开发板的核心板介绍
RK3568开发笔记(一):瑞芯微RK3568芯片介绍,入手开发板的核心板介绍
RK3568开发笔记(一):瑞芯微RK3568芯片介绍,入手开发板的核心板介绍
|
弹性计算 数据安全/隐私保护
【雾锁王国/Enshrouded】2024年阿里云服务器一键搭建雾锁王国游戏:轻松打造专属游戏世界
随着游戏行业的不断发展,玩家们对于游戏体验的要求也越来越高。为了满足玩家们的需求,阿里云提供了游戏联机服务器一键部署方案,本文将为大家分享基于阿里云服务器10秒钟完成雾锁王国游戏服务器搭建教程,让大家的游戏体验更加顺畅。
268 1
|
SQL HIVE
Hive分区+根据分区查询
Hive分区+根据分区查询
|
6月前
|
SQL 存储 NoSQL
Flink x Paimon 在抖音集团生活服务的落地实践
本文整理自抖音集团数据工程师陆魏与流式计算工程冯向宇在Flink Forward Asia 2024的分享,聚焦抖音生活服务业务中的实时数仓技术演变及Paimon湖仓实践。文章分为三部分:背景及现状、Paimon湖仓实践与技术优化。通过引入Paimon,解决了传统实时数仓开发效率低、资源浪费、稳定性差等问题,显著提升了开发运维效率、节省资源并增强了任务稳定性。同时,文中详细探讨了Paimon在维表实践、宽表建设、标签变更检测等场景的应用,并介绍了其核心技术优化与未来规划。
625 10
Flink x Paimon 在抖音集团生活服务的落地实践
|
网络协议 网络架构
OSI 模型和 TCP/IP 模型的异同
OSI 模型和 TCP/IP 模型的异同
393 1
|
存储 监控 Kubernetes
构建高效稳定的云原生日志监控系统
【5月更文挑战第26天】 随着微服务架构和容器化技术的普及,传统的日志监控方法面临重大挑战。本文将探讨如何构建一个既高效又稳定的云原生日志监控系统,该系统旨在提供实时的日志分析能力,同时保证系统的高可用性和可扩展性。我们将讨论利用现代技术栈如Fluentd、Elasticsearch和Kibana(EFK栈)来搭建日志收集、存储和可视化的解决方案,并深入探讨如何通过容器编排工具如Kubernetes来实现日志服务的自动伸缩和故障恢复。此外,我们还将介绍一些最佳实践,帮助运维团队在保持系统性能的同时,降低资源消耗和运营成本。
手机号段查询城市免费API接口教程
此接口用于根据手机号段查询相关信息,包括城市、运营商、区号等。支持POST和GET请求,需提供用户ID、KEY及手机号段前7位作为参数。返回数据包含状态码、信息提示及详细归属信息。示例请求地址:https://cn.apihz.cn/api/ip/haoduan.php?id=88888888&key=88888888&numbers=1321993。接口免费,建议使用个人ID与KEY以独享调用频次。
|
JavaScript Java Go
后端语言
【10月更文挑战第12天】后端语言
346 5
|
算法 Java 程序员
内存回收
【10月更文挑战第9天】
460 5
下一篇
oss云网关配置