- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
当编写需要多个独立随机数分布/序列的代码时(下面的示例有两个),似乎有两种典型的方法来实现(伪)随机数生成。一种是简单地使用 random_device
对象为两个独立的引擎生成两个随机种子:
std::random_device rd;
std::mt19937 en(rd());
std::mt19937 en2(rd());
std::uniform_real_distribution<> ureald{min,max};
std::uniform_int_distribution<> uintd{min,max};
另一个涉及使用 random_device
对象创建一个使用多个随机“源”的 seed_seq
对象:
// NOTE: keeping this here for history, but a (hopefully) corrected version of
// this implementation is posted below the edit
std::random_device rd;
std::seed_seq seedseq{rd(), rd(), rd()}; // is there an optimal number of rd() to use?
std::vector<uint32_t> seeds(5);
seedseq.generate(seeds.begin(), seeds.end());
std::mt19937 en3(seeds[0]);
std::mt19937 en4(seeds[1]);
std::uniform_real_distribution<> ureald{min,max};
std::uniform_int_distribution<> uintd{min,max};
在这两个之中,有没有首选的方法?为什么?如果是后者,是否存在用于生成 seed_seq
对象的最佳 random_device
“源”数量?
有没有比我上面概述的这两种实现方式更好的随机数生成方法?
谢谢!
(希望)针对多个分布的 seed_seq
实现的更正版本:
std::random_device rd;
std::seed_seq seedseq1{rd(), rd(), rd()}; // is there an optimal number of rd() to use?
std::seed_seq seedseq2{rd(), rd(), rd()};
std::mt19937 en3(seedseq1);
std::mt19937 en4(seedseq2);
std::uniform_real_distribution<> ureald{min,max};
std::uniform_int_distribution<> uintd{min,max};
最佳答案
std::seed_seq
通常用于您不信任默认实现来正确初始化您正在使用的引擎状态的情况。
在许多 ≥C++11 实现中,std::default_random_engine
是 std::mt19937
的别名,它是 Mersenne Twister 伪随机数的特定变体生成算法。 Looking at the specification for std::mt19937
,我们看到它的状态大小为 624 个无符号整数,足以容纳它打算包含的 19937 位状态(这就是它的名称)。传统上,如果您仅使用单个 uint32_t
值(如果 rd
为一个 std::random_device
对象),那么它的绝大部分状态都未初始化。
现在,如果您使用单个 uint32_t
值构造一个 std::mt19937
(如 std::default_random_engine engine{rd()};
),该实现需要通过置换原始种子值来初始化其余状态,因此虽然单次调用 rd ()
产生有限范围内的实际不同引擎状态,但它至少足以正确初始化引擎。这将产生一个“优质”的随机数生成器。
但是如果您担心引擎没有被正确播种,无论是出于密码原因(尽管请注意 std::mt19937
本身在密码学上是不安全的!)或者仅仅是出于统计原因,您可以使用 std::seed_seq
手动指定整个状态,使用 rd()
填充每个值,这样你就可以保证相对置信度引擎已正确播种。
对于随意使用,或并非绝对需要获得高质量随机数的场景,只需调用一次 std::random_device::operator()
即可进行初始化。
如果你想使用 std::seed_seq
,确保你设置正确(你的原始代码中的例子绝对不正确,至少对于 std::mt19937
,实际上会产生比简单使用 rd()
更糟糕的结果!)。 This post on CodeReview包含经过适当审查的代码。
对于Mersenne Twister的预定义模板,状态大小始终为19968位,比实际需要的略多,但也是使用uint32_t
值可以完整表示范围的最小值.这算出 624 个 Word,每个 32 位。因此,如果您计划使用种子序列,您将通过对 rd()
的 624 次调用正确地初始化它:
//Code copied from https://codereview.stackexchange.com/questions/109260/seed-stdmt19937-from-stdrandom-device
std::vector<uint32_t> random_data(624);
std::random_device source;
std::generate(random_data.begin(), random_data.end(), std::ref(source));
std::seed_seq seeds(random_data.begin(), random_data.end());
std::mt19937 engine(seeds);
//Or:
//std::mt19937_64 engine(seeds);
如果您正在使用 std::mersenne_twister_engine
的非标准实例化,则可以通过将其 state_size
乘以查询该特定情况所需的状态大小它的 word_size
然后除以 32。
using mt_engine = std::mersenne_twister_engine</*...*/>;
constexpr size_t state_size = mt_engine::state_size * mt_engine::word_size / 32;
std::vector<uint32_t> random_data(state_size);
std::random_device source;
std::generate(random_data.begin(), random_data.end(), std::ref(source));
std::seed_seq seeds(random_data.begin(), random_data.end());
mt_engine engine (seeds);
对于其他引擎类型,您需要根据具体情况对其进行评估。 std::linear_congruential_engine
及其预定义变体使用其字长的单个整数,因此它们只需要一次调用 rd()
即可初始化,因此种子序列是不必要。我不确定 std::subtract_with_carry_engine
或其关联的使用 std::discard_block_engine
是如何工作的,但它似乎也像它们一样只包含一个状态的Word。
关于c++ - 决定在 random_device 和 seed_seq 之间生成多个随机数序列的种子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47562404/
这是一道函数依赖题。 我知道当 x->yz 然后 x->y 和 x->z 时。但是上面的依赖关系可能吗? 最佳答案 If xy determines z can x determine z and y
我有一个奇怪的问题。 Line 61: $this->_currentRoute = Default_Model_Routes::getInstance()->getCurrentRoute(); .
我正在开发一种工具来比较两个波形文件的波形相似性。例如,我有一个持续时间为 1 分钟的波形文件,我使用第一个波形文件制作了另一个波形文件,但每 5 秒生成一次数据,间隔为 5 秒至 0。 现在我的软件
我遇到了一个奇怪的问题,尽管我打赌有一个巧妙的方法可以解决它。 情况是我有一个具有三列排序状态的表:完全未排序,在这种情况下我不希望出现任何图标,按升序排序,在这种情况下我想要一个向上箭头,以及按降序
Java 语言规范提供了criteria用于确定(格式良好的)执行是否满足“Java 内存模型的因果关系要求”。让我们假设执行是有限的。我试图了解是否存在多项式时间算法来证明或反驳这种情况。 真的,我
Java 语言规范提供了criteria用于确定(格式良好的)执行是否满足“Java 内存模型的因果关系要求”。让我们假设执行是有限的。我试图了解是否存在多项式时间算法来证明或反驳这种情况。 真的,我
我正在编写一个简单的Bank类,其中包含Account。我希望人员能够开设一个新的受密码保护的银行帐户,并从其帐户中提取和存入资金。账户设在银行内。银行和帐户类应提供哪些服务? 假设 p 已在银行 b
我的标题概括了这一点。我有一个将要开发的简单业务线应用程序,并且很好奇如何确定我应该针对哪个 .NET 版本。支持 Win XP SP3 会很好,但不是必需的。它将用于索引多页 tiff,因此导入一批
已锁定。这个问题及其答案是locked因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。 你是否真的“尝试过”(意味着在其中编程,而不仅仅是阅读有关它的文章)Erlang并决定在项目中
我正在尝试使用 ExceptionFilterAttribute 为 Web Api 实现异常处理。我已经继承了ExceptionFilterAttribute 类并覆盖了onException 方法
前一段时间在一次编程比赛中我遇到了一个令人费解的问题,此后一直困扰着我。虽然我没有逐字记住,但我会尽力重现: Jack starts at 0 on the number line and jumps
我有什么: 我有一个主要内容区域,后面跟着两个旁白: #primary,#secondary,#tertiary{float:left; width:33%;} Primary
我无法正确操作键盘。 整个 View 充满了文本字段。 当我使用通知将 View 向上移动时,上方的文本框不再可见: override func viewDidLoad() { super.v
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我在尝试获取父对象来过滤子事件时遇到问题。 在下面的示例中,我在旋转框上设置了一个事件过滤器。事件过滤器检测旋转框上的鼠标按下事件。然后,我希望父对象根据某些标准接受或忽略该事件。 问题是它似乎接受了
我使用从 std::system_error 继承的类进行错误处理,我想控制调用 what() 时返回的内容。原因:标准(C++11 和 C++1y CD 草案 - N3690,下面的 § 引用是后者
我正在用 Swift 构建一个 iOS 应用程序,它的起始页有 6 个按钮。这些按钮中的每一个都将连接到一个 TableView Controller ,其数据由 NSFetchedResultsCo
我想构建这样的东西 数据存储| mycode.py | RESTful API | mywebapp.py(Django 或 Tornado) 我检查了 Django 的 Piston,但似乎这样我就
究竟如何更改 RichTextBox 中的字体? 环顾四周给了我似乎不再有效的旧答案。我认为这就像执行 richtextbox1.Font = Font.Bold; 或类似操作一样简单。原来不是,所以
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 7 年前。 Improve this qu
我是一名优秀的程序员,十分优秀!