【发布时间】:2012-04-23 19:10:32
【问题描述】:
我正在使用此代码使用 Fisher-Yates 随机化算法的变体生成向量的随机排列(我是从第一个元素到最后一个元素,而不是相反)。我在一个程序中全局使用boost::random::mt11213b RNG,该程序在程序启动时以generator.seed(time(NULL)); 为种子,因此这里是一个包装器单例RandomNumber。
boost::random::uniform_int_distribution<unsigned long>
distribution(0, vec.size()-1);
for (unsigned long i=0;i<vec.size();i++)
std::swap(vec[i], vec[distribution(RandomNumber::getInstance().generator)]);
简而言之,一些实验让我相信这个算法可能存在问题。这就是我所做的
- 创建了一个长度为 100 的整数向量
- 用
0填充前75 个元素,用1填充最后25 个元素 - 洗牌一个数组。
- 从列表中取出前 5 个元素并将它们相加。
我重复这个过程几千次(循环,而不是手动:))每次都从一个新的向量开始。然后我计算了总和的算术平均值,结果是0.98,而不是预期的1.25。
有趣的是,如果我从一个用相同算法而不是有序算法洗牌一次的向量开始,结果会增加到1.22,如果我在每次迭代中不丢弃向量而是再次随机播放,结果大约是1.25,这是预期值。
我不确定可能出了什么问题。该算法看起来不错,我能想到的唯一可能出错的是播种阶段和
boost::random::uniform_int_distribution<unsigned long>
distribution(0, vec.size()-1);
在洗牌向量之前每次调用的行(也许它应该只在程序中调用一次,但这没有任何意义)
任何帮助将不胜感激!
【问题讨论】:
-
如果我不得不猜测原因,您不会每次都在循环中更改分布大小。 计算机编程艺术算法是here。
-
那没有意义。向量的长度是固定的。
-
是的,但是一旦你洗牌到 n 个元素,你就不想再碰第一个 n 了,因为伪随机数的重复应用不会让事情变得更随机,它们会让它们变得更少随机。
-
您列出了实验中采取的步骤 - 听起来代码(或至少与您的描述完全相同的代码)应该足够短才能发布。这样 OmnipotentEntity 就不必猜测了(但是有了这样的名字,我很惊讶无论如何都涉及到任何猜测:))。
-
天哪,当我第一次阅读算法时,我完全误解了它。谢谢,你可以发布一个答案,所以我可以接受。
标签: c++ boost random probability boost-random