STL随机分布和可移植性

8

为什么标准分布的结果不需要在不同实现之间保持一致?而伪随机数生成器的结果则必须相同。

例如,对于每个不同的标准库实现,以下代码几乎肯定会打印出不同的结果。

std::mt19937 random {100};
std::normal_distribution<> dist;

std::cout << dist(random);

假设我想进行程序生成,并希望相同的起始种子能在不同平台和编译器上产生相同的结果。然而,使用STL无法实现这一点,必须“退回”使用boost。为什么这不是一个缺陷?


1
这不是一个答案,只是一个值得思考的问题。对于许多发行版来说,有多种方法可以获得所需的值。正态分布可以使用Box-Muller变换或(递归或泰勒展开)误差函数。这两种方法都使用其他函数(如余弦、正弦、对数、误差函数、积分、平方根...)。很难说哪种方法最好(时间 vs. 精度),哪种方法可以最优化。也许在C++14中,当人们更熟悉这些分布和实现时,会强制执行标准。 - druckermanly
哦,甚至Box-Muller变换也有不同的(极坐标,笛卡尔)实现。无数种方法,无尽乐趣? - druckermanly
@user2899162,你的理解是正确的,我在我的回答中引用了这个提案。 - Shafik Yaghmour
1个回答

13
这不是一个缺陷,而是一种设计。其背后的原因可以在向标准库添加可扩展伪随机数工具箱的提案(N1398)中找到,该提案表示(强调我的):
“另一方面,分布的规范仅定义统计结果,而不是要使用的精确算法。这与引擎不同,因为对于分布算法,它们的正确性的严格证明是可用的,通常在输入随机数(真正)均匀分布的前提下。例如,至少有一些算法已知可以从均匀分布的随机数产生正态分布的随机数。哪一个算法最有效取决于各种超越函数的相对执行速度、CPU的缓存和分支预测行为以及所需的内存使用。因此,该提案将算法的选择留给了实现。由此导致分配输出序列在实现之间不会完全相同。预期实现将事先谨慎地选择分布的算法,因为某些分布从一个实现版本到另一个实现版本产生不同的数字肯定会让客户感到惊讶。”
这一点在实现定义部分中得到重申,该部分表示:
“如何生成各个分布的算法被指定为实现定义,因为已知每个分布有大量的算法。每个算法在速度、对最近的计算机架构的适应性和内存使用方面具有不同的权衡。实现需要记录其选择,以便用户可以判断是否接受其质量。”

2
可爱的;因此,如果一致性在实现中很重要,那么必须采用非标准库的方法。感谢提供有关提案的相关摘录。 - Brandon
@Brandon,这就是我能找到的所有信息了,看起来是这样的。你可以在ISO C++标准-讨论上提出这个问题,看看是否有改进的空间。 - Shafik Yaghmour
不是个坏主意。像在<cstdint>中所做的那样,在快速和稳定之间进行选择会很不错,尽管有点凌乱。再次感谢。 - Brandon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接