使用 boost::random 洗牌向量时出现问题
Issue when shuffling a vector with boost::random
我正在使用这段代码来生成一个向量的随机排列,使用费舍尔-耶茨随机化算法的变体(我从第一个元素到最后一个元素,而不是相反)。我正在一个程序中全局使用 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);
每次在向量被洗牌之前调用的行(也许它应该只调用一次程序,但这没有意义)
任何帮助将不胜感激!
如果我必须猜测原因,您不会每次循环都更改分布大小。计算机编程算法的艺术就在这里。
一旦你洗牌到n个元素,你就不想再碰前n个,因为重复应用伪随机数不会让事情变得更随机,而是使它们不那么随机。
不,你的算法是错误的。考虑向量为 4 个数字的简单情况,您的算法返回以下有偏差的结果
result probability * 256
{1,2,3,4} 10
{1,2,4,3} 10
{1,3,2,4} 10
{1,3,4,2} 14
{1,4,2,3} 11
{1,4,3,2} 9
{2,1,3,4} 10
{2,1,4,3} 15
{2,3,1,4} 14
{2,3,4,1} 14
{2,4,1,3} 11
{2,4,3,1} 11
{3,1,2,4} 11
{3,1,4,2} 11
{3,2,1,4} 9
{3,2,4,1} 11
{3,4,1,2} 11
{3,4,2,1} 10
{4,1,2,3} 8
{4,1,3,2} 9
{4,2,1,3} 9
{4,2,3,1} 8
{4,3,1,2} 10
{4,3,2,1} 10
而标准的费雪-耶茨算法将为所有结果提供一致的概率。
如果要洗牌向量,请直接使用 std::random_shuffle
(有关一些示例代码,请参阅使用 boost::random 作为 std::random_shuffle 的 RNG)。
相关文章:
- 如何在C++向量中奇数元素前面加上值-1,我在使用insert函数时遇到了问题
- 添加存储在向量中的大整数的函数出现问题
- C++ 继承向量问题(无限循环+在其他类中使用向量的问题)
- SWIG c++到python:向量问题
- 向量问题,如何删除向量中的数组?
- 向量问题,也许有点手
- ndk中的标准与cpp向量问题
- 从数据文件到多维向量问题
- C++:向量问题的向量
- 类向量 c++ 问题
- 特征向量问题
- C++std::向量问题
- 结构中的向量问题
- C++类向量问题
- 向量的向量问题
- 获取索引和元素-向量问题
- 搜索或发现向量问题内部
- C++向量问题;通过引用传递内容
- 几个c++向量问题
- 指向包含向量问题的实例类的指针<int>