使用 Rand7() 实现 Rand10()(C++)2025年3月21日 | 阅读 6 分钟 随机数生成是大多数算法和应用程序的基本组成部分,从简单的模拟到 加密 应用。很多时候,我们可能会遇到现有随机数生成器不足的情况。例如,假设 Rand7() 是一个生成 {1, 2, 3, 4, 5, 6, 7} 集合中均匀随机整数的现有函数。然而,解决特定任务需要创建 Rand10(),它是一个仅范围在 1 到 10 的随机整数。这个问题看似简单,但要保证游戏的公平性,即保证 10 种可能结果的概率相等,并非易事。 用 Rand7() 来定义 Rand10() 不仅是一个编程问题,也是深入了解随机性本质以及一种随机分布如何转化为另一种随机分布的绝佳机会。这个问题通常出现在技术面试和编程竞赛中,既作为理论问题也作为实践问题。 Rand7() 在生成随机数方面的最大难点在于它只有七种不同的结果,并且所有结果的概率都相同。因此,另外三种结果也必须独立且均匀地选择,以便能够均匀地选择 1 到 10 之间的数字。这是一个需要认真对待的重要方面,并且需要一种方法来以平等的标准实现这两个范围之间的匹配。 在这篇文章中,我们将讨论这个问题,回顾解决问题背后的 数学 概念,然后逐步描述在 C++ 中实现的解决方案。首先,我们将考虑问题及其所有特殊性,然后考虑有助于找到解决方案的思维方式。最后,我们将对解决方案进行离散化,使代码既高效又正确。在本文结束时,您不仅将获得 Rand10() 的实现,还将理解生成随机数的原理及其在计算机科学领域的重要性。 理解问题为了理解这个问题,让我们首先详细了解 Rand7() 函数。此函数返回 1 到 7 范围内的随机整数,并且该范围内的每个值都是可能的。换句话说,数学上,获得任何特定数字(假设为 x,其中 x 是介于 1 和 7 之间的整数)的概率是 P(x) = 1/7。 现在让我们来讨论需要创建的 Rand10() 函数。顾名思义,此函数应生成一个介于 1 到 10 之间(包括 1 和 10)的整数,并且该函数的每个整数结果都应具有相等的概率 p(y) = 1/10。这里的任务是仅使用 Rand7() 来获得 Rand10(),同时保持 1 到 10 的数字概率相等。 核心问题在于 Rand7() 产生七个结果,而 Rand10() 需要十个结果。换句话说,没有一种方法可以将 Rand7() 的七个结果映射到 Rand10() 所需的十个结果,同时避免偏差。原始意图是将 7 个结果映射到 Rand7() 的 10 个可能结果。如果将得到的结果移至 1:10 的范围,则某些数字将被过度近似,这将违反等密度规则。 为了解决这个问题,我们必须开始使用更多的潜在结果,以便可以将 1 到 10 的数字均匀地等同起来。所使用的技术之一是通过汇总 Rand7() 的调用结果,以获得更大的结果范围。因此,如果我们调用两次 Rand7(),我们可以得到一个介于 1 到 49 之间的数字集合(因为 7*7=49)。这个足够大的范围提供了比随机过程潜在结果更多的数字变化,我们可以使用模运算和拒绝采样来使随机数在 1 到 10 的数字范围内均匀分布。 编码 输出 Distribution of numbers generated by Rand10() over 1000000 trials: 1: 100064 times (10.0064%) 2: 99954 times (9.9954%) 3: 100095 times (10.0095%) 4: 99836 times (9.9836%) 5: 100076 times (10.0076%) 6: 100145 times (10.0145%) 7: 99965 times (9.9965%) 8: 100074 times (10.0074%) 9: 100128 times (10.0128%) 10: 99663 times (9.9663%) 说明
结论总之,如何使用 Rand7() 实现 Rand10() 的问题是元数学和随机分布转换实际应用的又一个例子。该解决方案还基于多次获得 Rand7() 的总体可能性变化,并使用拒绝采样作为一种有助于使值范围更加多样的技术。通过仔细将结果缩放到 1 到 10 的范围,该方法确保所有数字都具有相同的概率。这种方法不仅能够解决特定问题,还能通过利用数学思维和算法方法的强大功能来获得均匀性,从而对如何处理随机化和类似问题提供更深入的理解。 下一主题C++ 中的两数 LCM |
在本文中,我们将讨论 C++ 中的 std::countr_zero 方法及其语法和示例。C++ 中的 std::countr_zero() 方法是什么?countr_zero 函数在 C++20 中引入。此函数位于 <bit> 头文件中。此函数用于计算末尾零的数量...
阅读 4 分钟
在本文中,我们将讨论C++中的std:nothrow,包括其语法、参数、示例和优点。它允许我们摆脱使用语言自带语法的单调性,并创建更简单、更直观、更高级的代码。什么是...
阅读 4 分钟
简单的基于 RAII 的互斥锁 std::lock_guard 在构造时锁定互斥锁,在销毁时释放它,而不提供用户控制。另一方面,std::unique_lock 函数更加灵活,因为它允许所有权转移、定时锁定、手动解锁和延迟锁定。对于...
阅读 10 分钟
C++ 程序异常行为通常会导致程序崩溃。您可能遇到过几种问题,例如段错误、终止、浮点异常等等。以下示例程序可以帮助您了解 C++ 应用程序崩溃的原因。1. 异常 C++ 中的异常...
阅读 3 分钟
笛卡尔树排序是一种独特的排序算法,它利用笛卡尔树信息结构来实现高效的数字排序。要理解这套规则,深入了解笛卡尔树的概念、它们的生成以及...
阅读 12 分钟
C++ CLI 和 C++/CX 是 C++ 编程语言的扩展,它们支持与 .NET 框架的互操作性。然而,它们在设计、用法和目标环境方面具有共性。本文将详细解释这两种技术,并以表格格式提供比较分析。什么...
5 分钟阅读
在本例中,我们将讨论一个问题。问题陈述:假设我们有一个 n × n 的字符网格,其中包含星号 (*) 和点 (.)。除两个单元格外,所有单元格都用点表示。我们需要将另外两个单元格标记为角点以创建...
阅读 6 分钟
简介 这是“反转单词前缀”问题的核心,该问题构成了算法的基础,并涉及通过反转从开头到给定字符(包括该字符)的段来重构字符串。给定一个字符串 word 和一个字符......
7 分钟阅读
勒让德猜想(Legendre's Conjecture)是一个陈述,即两个连续自然数的平方之间总是存在一个素数。在本文中,我们将讨论勒让德猜想及其算法和实现。数学陈述:在任意两个连续自然数的平方之间存在一个素数 p...
7 分钟阅读
海景的魅力是永恒的,超越了世代和文化。站在繁华都市的边缘,看着海浪拍打海岸,会唤起一种宁静、敬畏和灵感的感觉。对许多人来说,拥有一个享有无遮挡视野的房产的前景……
阅读 12 分钟
我们请求您订阅我们的新闻通讯以获取最新更新。
我们提供所有技术(如 Java 教程、Android、Java 框架)的教程和面试问题
G-13, 2nd Floor, Sec-3, Noida, UP, 201301, India