【计算机程序设计艺术 TAOCP】卷2·3.1 引言:程序怎样产生“随机数”

Shuffle双面性:从Knuth洗牌算法到大数据shuffle机制解析 洗牌(Shuffle)是编程与分布式计算中常遇的概念,既指将序列随机重排的算法操作,也指大数据引擎中跨节点重新分配数据的关键阶段。在算法层面,Fisher-Yates(也称Knuth Shuffle)以严格等概率和O(n)复杂度成为标准实现;在大数据层面,shuffle决定MapReduce与Spark作业的性能,涉及排序、分区、网络与磁盘开销。理解两者的区别与联系,有助于开发者在游戏抽奖、随机抽样、数据倾斜治理等场景做出正确技术选型。本文从概率原理、代码实现、统计验证到大数据调优,系统梳理shuffle的 阅读详情

对应原书:第2卷《半数值算法》第3版,§3.1,书页1至8。第3章从本卷开始,主题是随机数。本文按原书的问题顺序展开,例子和 Python 程序为讲解重新设计。

写一个计算平方的函数,我们希望同一个输入总得到同一个结果。写一个随机数生成程序,我们又希望它的输出没有容易利用的规律。这两个要求放在一起,似乎有些冲突。

§3.1 先让我们面对这个问题:如果计算步骤完全确定,所谓“随机”究竟从哪里来?理解这一点,后面的周期、统计检验和分布转换才不会变成互不相干的技巧。

1. 应用需要的是一串数的性质

原书列出随机数的许多用途,包括模拟、抽样、数值分析、程序测试,以及某些带随机选择的算法。

以排队模拟为例,程序可能需要生成顾客到达的间隔、服务所用的时间,再据此估计等待长度。以抽样为例,我们可能希望从一万条记录中选出一百条,让每条记录有相同的入选机会。

这些任务需要的“随机”并不只是一张杂乱的数字表。

若每次到达间隔都符合目标分布,但相邻两次间隔总是一长一短,队列的行为仍然可能被改变。若抽样时每个位置单独看都差不多公平,但总把相邻记录一起选中,样本的联合分布也可能不对。

因此,至少需要分清两个问题:

  • **单个输出的分布:**哪些值可以出现,各自有多大概率?
  • **多个输出的关系:**前面的值是否影响后面的值,哪些组合会被过多或过少地产生?

本章首先研究0与1之间的一致分布,也常称均匀分布。理想模型是

U 0 , U 1 , U 2 , … 相互独立,且服从  U [ 0 , 1 ) . U_0,U_1,U_2,\ldots \quad\text{相互独立,且服从 }U[0,1). U0​,U1​,U2​,…相互独立,且服从 U[0,1).

在这个模型下,长度为 b − a b-a b−a 的区间 [ a , b ) [a,b) [a,b) 得到的概率就是 b − a b-a b−a。独立性还要求,例如连续两项都落在 [ 0 , 1 / 2 ) [0,1/2) [0,1/2) 中的概率为 1 / 4 1/4 1/4。

计算机实际给出的只是有限精度的数,因此这个连续模型是分析目标;具体程序还需要说明它怎样把整数状态映射到有限网格上。

2. 可复现是伪随机数的一项用途

设生成程序保存状态 S n S_n Sn​,每调用一次执行

S n + 1 = T ( S n ) , X n = g ( S n ) . S_{n+1}=T(S_n),\qquad X_n=g(S_n). Sn+1​=T(Sn​),Xn​=g(Sn​).

初始状态由种子确定。如果 T T T 和 g g g 都是确定函数,相同初始状态就会重放相同的输出。

在调试模拟程序时,这很有用。一次运行出现异常后,保存初始状态和调用过程,就能回到当时的数据条件。若每次重跑都换成另一串数,我们反而很难判断,是程序修改起了作用,还是输入恰好变了。

但“能够重放”和“适合模拟”是两个需要分别验证的性质。一个计数器

0 , 1 , 2 , 3 , … , 9 , 0 , 1 , 2 , 3 , … 0,1,2,3,\ldots,9,0,1,2,3,\ldots 0,1,2,3,…,9,0,1,2,3,…

当然可以重放,每个数字在完整周期中出现得也一样多;它却能被轻易预测,而且相邻数字的关系完全固定。

种子也不是让糟糕方法突然变好的开关。更换种子可能只是在同一个循环上换一个出发位置。后面研究生成器时,我们会把“状态怎样演化”和“初始状态怎样选取”分开讨论。

3. 有限状态为什么必然重复

假设程序只有 M M M 个可能状态,并且运行过程中没有加入新的外部输入。观察

S 0 , S 1 , … , S M S_0,S_1,\ldots,S_M S0​,S1​,…,SM​

这 M + 1 M+1 M+1 个状态,按抽屉原理,至少有两个相同。若 S i = S j S_i=S_j Si​=Sj​ 且 i < j i<j i<j,确定性就给出

S i + t = S j + t , t ≥ 0. S_{i+t}=S_{j+t},\qquad t\geq0. Si+t​=Sj+t​,t≥0.

从这时开始,后面的演化也会重复。轨道因此可以分成两段:进入循环以前的长度 μ \mu μ,以及循环本身的长度 λ \lambda λ。

初始状态 → …… → 循环入口 → …… → 循环入口 → ……
             前段长 μ       循环长 λ

这里判断的是完整状态。一个输出值出现两次,并不一定意味着程序状态已经重复。例如,状态中还保存了其他数,或者输出只取了状态的一部分。

反过来,状态重复一定会使后续输出重复。输出序列的最小周期也可能比状态周期更短,因为不同状态可能被 g g g 映射到同一个值。

这个结论直接说明两件事:无限期不重复不是固定有限状态程序能做到的;周期虽然重要,也只是有限状态结构的一个指标。

4. 平方取中法:复杂的数字变化也可能很快塌缩

原书介绍了平方取中法:保存一个固定长度的十进制整数,平方后补齐位数,取中间几位作为新状态。

以四位状态为例:

6100 2 = 37210000 , 中间四位为  2100. 6100^2=37210000,\qquad\text{中间四位为 }2100. 61002=37210000,中间四位为 2100.

继续计算会得到

6100 → 2100 → 4100 → 8100 → 6100

这正是原书展示的一种短循环。另一个问题是0:它的平方仍为0,一旦进入就无法离开。

下面把“补齐八位”明确写进程序,避免把前导零丢掉。orbit 返回重复前出现过的不同状态、前段长度和循环长度。它只适合状态数较少的教学检查,空间占用与访问过的状态数成正比。

def middle_square4(x):
    if not isinstance(x, int) or not 0 <= x < 10000:
        raise ValueError("x must be a four-digit state")
    digits = f"{x * x:08d}"
    return int(digits[2:6])


def orbit(seed, step, max_states):
    if max_states <= 0:
        raise ValueError("max_states must be positive")
    seen, states = {}, []
    x = seed
    while x not in seen:
        if len(states) >= max_states:
            raise ValueError("state bound was too small")
        seen[x] = len(states)
        states.append(x)
        x = step(x)
    mu = seen[x]
    return states, mu, len(states) - mu


states, mu, period = orbit(6100, middle_square4, 10000)
print(states, mu, period)
print(orbit(1000, middle_square4, 10000))
assert orbit(6100, middle_square4, 10000) == (states, mu, period)
assert middle_square4(0) == 0

输出:

[6100, 2100, 4100, 8100] 0 4
([1000, 0], 1, 1)

第二行说明:种子1000只经过一步就进入0的固定点。种子看上去有四位,并不能保证得到很长的轨道。

§3.1 还讨论了一个拼接许多操作的复杂生成方案。它的价值在于反例:增加条件分支、交换数字或组合算术操作,并不会自动获得可证明的好性质。判断方法仍然要回到状态结构与输出行为。

5. “每个数字一样多”为什么不够

考虑长度为100的二进制串:

0101010101……

它包含50个0和50个1。如果只检查单个数字的频数,这个结果完美得近乎刻意。但观察相邻两位,00 和 11 从来不出现;知道当前位,就知道下一位。

再看真正独立的100次公平抛硬币。令1的个数为 H H H,则

E [ H ] = 50 , Var ⁡ ( H ) = 25. \mathbb E[H]=50,\qquad \operatorname{Var}(H)=25. E[H]=50,Var(H)=25.

50是均值,不是每次实验必须恰好达到的指标。把输出强行修正成50个0、50个1,会引入新的约束:前99位一旦确定,最后一位便可能被迫取某个值。

所以,检验中既需要寻找明显偏差,也要警惕不合理的“过度整齐”。不过,一个样本恰好平衡本身不构成错误证据;要判断它在指定模型和重复实验中是否异常。

同样,一段很长的连续0也不能单独证明生成器坏了。它的可疑程度取决于观察长度、检查规则和我们提出的问题。先看结果再挑一个最显眼的模式,会改变判断的概率背景。

6. 带着哪些问题进入下一节

接下来可以给每个生成方案记一份简短记录:

要记录什么它能帮助回答什么
完整状态与更新公式哪些信息决定后续输出
种子的合法范围是否会进入零状态或特殊短循环
周期与证明条件至少多久以后一定重复
输出映射方式是否只使用了较差的位,是否产生额外偏差
针对联合分布的检验频数之外还有哪些依赖
实际调用方法应用取相邻值、隔项值,还是按某种条件取值

最后一行容易遗漏。生成器的数只有进入应用以后,才真正形成到达时间、坐标、排列或样本。应用如何消费输出,也会影响结果。

§3.2 将从最容易写下、也最值得认真分析的一类递推开始:线性同余法。我们要寻找的并非看起来最复杂的公式,而是参数、周期和结构都能够说明白的方法。


阅读定位:§3.1 开头的应用与随机性讨论见书页1至3;平方取中法和复杂生成方案的反例见3至6页;随后习题可用于练习周期与有限状态分析。上一篇为卷1·2.6,下一篇为卷2·3.2。

专栏:计算机程序设计艺术 TAOCP。底本:Donald E. Knuth 著,苏运霖译,《计算机程序设计艺术》第2卷《半数值算法》第3版,国防工业出版社,2002年版。

LangChain学习及应用(超详细) Model I/O 部分是与语言模型进行交互的核心组件,包括输入提示(Prompt Template)、调用模型(Model)、输出解析(Output Parser)。简单来说,就是输入、处理、输出这三个步骤。LLM 因其具有海量参数,需要花费相当的物力与时间成本进行预训练和微调,同时商用 LLM 还需要进行各种安全测试与风险评估等。因此 LLM 会存在知识滞后的问题。在专有领域,LLM 无法学习到所有的专业知识细节,因此在面向专业领域知识的提问时,无法给出可靠准确的回答。 阅读详情

相关推荐

Matlab图像处理频域滤波实现——高斯低通、高通、带通带阻滤波器

如果你想要进一步了解更多的相关知识,

小嘤熊的博客 1万+

书籍-高德纳《计算机程序设计艺术》

《计算机程序设计艺术》是计算机科学领域最权威、最全面的理论著作,被誉为"计算机科学的圣经"。这套书不仅涵盖了算法和数据结构的方方面面,更重要的是它建立了计算机科学的数学基础和理论框架。

d3y1`5 81_09 1673

RC模型车多电机驱动方案:从电调PWM原理到四电机安全连接实战

在电机控制领域,PWM(脉冲宽度调制)是实现精确调速的核心技术。其原理是通过调节固定周期内高电平的脉宽来编码控制指令,进而驱动电子调速器(电调)改变输出功率。这项技术对于需要多电机协同工作的场景,如RC模型车的差速转向或重型负载驱动,具有关键价值。它能实现动力的精细分配与同步,提升车辆的可控性与通过性。在实际应用中,为确保系统稳定,必须关注电流分配与信号同步问题。例如,通过为每个电机配备独立电调并采用信号并联(Y线)的方式,可以构建可靠的四电机驱动系统。这种方案能有效避免因单个电调过载或电机反电动势不一致导

weixin_30664615的博客 381

应该怎样读TAOCP

应该怎样读TAOCP 2008年12月20日 星期六 下午 09:36 计算机程序设计艺术 第1卷 基本算法(第3版)(英文影印版)的评论      谈谈我自己读这套书的心得。抛砖引玉。        首先要清楚这套书的定位:它是古

junecau的专栏 1772

【数据挖掘】遗传算法原理浅析:什么是遗传算法?遗传算法的工作原理是什么?

遗传算法(Genetic Algorithm,GA),是进化算法的框架和核心。 各种进化算法有什么异同? - 及时物语的回答 - 知乎 https://www.zhihu.com/question/39152390/answer/901070749

纸羊同学的博客 4268

告别配置迷茫:手把手教你用Vivado 2023.1配置Xilinx FPGA的DDR4 MIG IP核(含AXI接口详解)

本文详细介绍了如何在Vivado 2023.1中配置Xilinx FPGA的DDR4 MIG IP核,包括AXI接口的深度解析与优化。通过实战案例和调试技巧,帮助工程师快速掌握DDR4内存与FPGA的协同工作,提升系统性能。特别适合需要高性能计算和实时信号处理的开发者。

weixin_29231725的博客 436

《算法导论》和《计算机程序设计艺术》下载地址

《Introduction to Algorithms》 作者:Thomas H.Cormen, Charles E.Leiserson, Ronald L.Rivest, Clifford Stein(CLRS) [img]http://mitpress.mit.edu/images/products/books/0262032937-f30.jpg[/img] 简称为CLRS的,被称作"...

hideto 3302

IDEA中Maven工具栏与命令执行全攻略:高效开发必备技巧

IntelliJ IDEA 作为强大的 Java 开发工具,其 Maven 功能独具优势。Maven 工具栏位于工作区右侧,图标功能丰富,涵盖项目导入、源码处理、依赖操作等。执行 Maven 命令有多种途径,Run Anything 窗口可输入或选目标执行,上下文菜单能右键运行目标,还可创建运行配置,指定命令参数后运行,为开发者高效管理 Maven 项目、便捷执行命令提供有力支持。

2301_82300081的博客 2027

程序史上最重要神作《计算机程序设计艺术》第四卷B新章节预览发布

(点击上方蓝字,可快速关注我们)来源:TechBang或许你不知道高德纳(Donald Ervin Knuth)是谁,甚至可能没有读过他的著作,但是事实上任何资工科系的学...

redditnote的博客 2020

UltraScale系列底层结构(3)——URAM概述

在UltraScale+™ 器件中,除了我们在常规熟悉的BRAM资源以外,还额外提供了URAM(UltraRAM)资源。 UltraRAM 是一种单时钟同步操作的高密度存储器,每个 UltraRAM 块可存储 288 Kb 数据,配置为 4K x 72 位的存储单元,其容量是 Block RAM 的八倍。虽然 UltraRAM 内部使用单端口存储单元,但通过在一个时钟周期内顺序执行端口 A 和端口 B 的操作,实现了双端口功能。

apple_53311083的博客 2828

化工管道设计软件:CAESAR II二次开发_(6).API接口与函数库

自定义函数库是开发者根据特定需求编写的函数集合。这些函数可以扩展CAESAR II的功能,实现更复杂的管道设计任务。自定义函数库通常需要开发者具备一定的编程基础,能够理解和编写与CAESAR II接口兼容的代码。定义函数:在Python或其他编程语言中定义所需的函数。注册函数:将自定义函数注册到CAESAR II的函数库中。调用函数:在CAESAR II中调用自定义函数,实现特定功能。假设我们需要创建一个自定义函数库,用于批量修改管道节点的坐标。定义函数:在Python中定义一个函数,用于批量修改节点坐标。

kkchenjj的博客 1726

【计算机程序设计艺术 TAOCP】卷2·3.2 生成一致随机数:周期很长,为什么仍然不够

推导线性同余递推,解释满周期条件、二进制低位的短周期和效能;用仿射变换复合实现快速跳步,避免错误使用模逆元,再梳理延迟递推、移位异或、逆同余和组合方法。

FreshManInC的博客 217

程序化广告ADX系统架构设计与实现

摘要: 本文详细介绍了程序化广告交易平台(ADX)的系统架构设计与实现。ADX作为连接广告主与媒体的核心平台,采用基于腾讯云和阿里云的微服务架构,包含网络基础设施、负载均衡、消息处理、核心业务服务和多级数据存储等层次。重点解析了Kafka消息队列处理高并发广告请求、Redis实时统计关键指标等核心技术实现,并提供了Java代码示例展示广告请求处理、竞价流程等核心功能。该系统通过分层设计和分布式组件,实现了高性能、高可用的程序化广告交易能力。

私聊前往站内信:https://i.youkuaiyun.com/#/msg/chat/weixin_44976692 764

计算机程序设计艺术 介绍

《计算机程序设计艺术》(The Art of Computer Programming),簡稱TAOCP,是高德纳(Donald Ervin Knuth)编著的关于计算机程序设计的七卷本著作。作者並因此获得美国计算机协会1974年图灵奖。[1]目录[隐藏]1 概述2 章節3 第4A卷,列舉與

Xiao_Qiang_的专栏 2570

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

与高德纳同行:读懂这套书,就读懂了程序的灵魂!

在已出版的书目中,卷 1 主要介绍基本算法,卷 2 主要介绍半数值算法,卷 3 主要介绍排序与查找,卷 4 主要介绍组合算法,卷 5、6、7 将分别介绍语法算法、语言理论和编译器。卷 4A 和卷 4B 均为组合算法相关内容,已出版的卷 4A 主要涉及布尔函数、按位操作技巧、元组和排列、组合和分区以及所有的树等,而卷 4B 的内容于 2022 年 10 月出版,如今中文版也即将出版!在高德纳目前的计划中, 卷 4 将分为 4A、4B、4C 等,每本书的标题均为《组合算法:Part 1、2、3……

图灵教育 291

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

【计算机程序设计艺术 TAOCP】卷2·3.3 统计检验:频数正常,能说明多少问题

从卡方与KS统计量出发,说明频数检验、相邻组合和理论检验各自能说明什么。用精确算术展示一维完全平衡却存在强依赖的序列,并解释谱检验所研究的格与平行平面结构。

FreshManInC的博客 175

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

050替代选择排序

替代选择排序由E.H. Friend提出,Knuth系统化并证明其平均归并段长为2M。该算法在磁带时代用于外部排序,通过最小堆动态生成有序段,显著减少归并轮次。其核心是:输出堆顶后,若新元素≥前一输出则续接当前段,否则冻结至下一段。适用于内存受限场景,提升外排序效率,成为数据库与操作系统中外部排序的理论基石。

平行教师朱宗晓的专栏 282

A10 恶劣环境传感器信号仿真与统计检验台

本项目基于《计算机程序设计艺术》算法库,开发恶劣环境下的传感器信号仿真与统计检验系统。核心实现滞后斐波那契生成器(LFG)算法,配合卡方拟合优度检验和间隔检验,构建工业级随机数质量评估平台。系统采用循环队列维护55个历史状态,通过严格的数学统计方法验证信号质量,对比分析LFG与传统LCG算法的性能差异。项目强调工程伦理,通过历史案例(如RANDU灾难)警示盲目信任输入源的风险,培养科学验证精神。提供完整的C语言实现路径,包括算法实现、统计检验和可视化报告功能,形成可证伪的数字风洞试验台。

平行教师朱宗晓的专栏 248

047基数交换排序

基数交换排序由Seward于1954年提出,Knuth在1973年系统化。它基于二进制位从高位开始分区,递归处理0/1子集,实现线性时间整数排序。适用于内存受限场景,优于比较排序下界。算法通过按位划分原地排序,支持负数(符号位为最高位),最终需将负数移至前端以保证升序。经多组测试验证,结果正确且高效。

平行教师朱宗晓的专栏 37

计算机科学经典著作

1.The Art of Computer Programming&lt;!--Attachment id="139306" thumb="http://img.verycd.com/post_thumbs/0601/post-54558-1137984966_thumb.jpg"--&gt;&lt;!--End Attachment--&gt;  Author: Donald.E.Knuth  ...

yaasshole 182

033水库抽样 - 从未知大小的流中等概率采样

水库抽样算法摘要 水库抽样是一种流式随机采样算法,由Donald Knuth在1969年提出基础版本(Algorithm R),Alan Vitter在1985年提出高效版本(Algorithm Z)。该算法能在未知数据总量N的情况下,仅用单次扫描和O(k)空间,从数据流中均匀抽取k个样本。 核心思想是维护一个大小为k的"水库",对第i个元素(i>k)以k/i的概率决定是否替换水库中的随机元素。数学证明保证每个元素被选中的概率严格等于k/N。该算法解决了磁带时代大数据采样难题,现广

平行教师朱宗晓的专栏 424

032Fisher-Yates洗牌算法 - 完美均匀的随机排列

摘要:Fisher-Yates洗牌算法由统计学家Fisher和Yates于1938年发明,用于农业实验随机化。Knuth等人将其改进为O(n)时间复杂度。该算法通过从后往前随机交换元素,确保每种排列出现的概率完全相等(1/n!),成为现代编程语言洗牌功能的基础。算法具有完美均匀性、原地操作和线性时间等优势,广泛应用于游戏、音乐播放等需要随机排列的场景。C语言实现包含洗牌函数、完整性验证和均匀性统计检验功能。

平行教师朱宗晓的专栏 373

Study Day32 11.7

Study Day32 11.7 R 英文 译法 1 译法 2 译法 3 race condition 条件竞争 竞态条件 radian 弧度 Redundant Array of Independent Disks, RAID 冗余独立磁盘阵列 raise 引起 random number 随机数 range 范围 区间 rank (矩阵)秩 排名 rapid prototyping 快速原型开...

weixin_43117503的博客 322
上一篇: 【计算机程序设计艺术 TAOCP】卷1·1.2 数学准备:从一个循环到精确分析
下一篇: 【计算机程序设计艺术 TAOCP】卷2·3.2 生成一致随机数:周期很长,为什么仍然不够
Js.Tx
博客等级 码龄8年 332粉丝 59原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值