C++ 两个值的随机选择

C++ 两个值的随机选择,c++,algorithm,random,C++,Algorithm,Random,在我的算法中,我需要随机选择两个值,但每一个值都必须选择预定的次数 到目前为止,我的解决方案是将选择放入正确次数的向量中,然后将其洗牌。在C++中: // Example choices (can be any positive int) int choice1 = 3; int choice2 = 4; int number_of_choice1s = 5; int number_of_choice2s = 1; std::vector<int> choices; for(i

在我的算法中,我需要随机选择两个值,但每一个值都必须选择预定的次数

到目前为止,我的解决方案是将选择放入正确次数的向量中,然后将其洗牌。在C++中:

// Example choices (can be any positive int)
int choice1 = 3; 
int choice2 = 4;

int number_of_choice1s = 5;
int number_of_choice2s = 1;

std::vector<int> choices;
for(int i = 0; i < number_of_choice1s; ++i) choices.push_back(choice1);
for(int i = 0; i < number_of_choice2s; ++i) choices.push_back(choice2);
std::random_shuffle(choices.begin(), choices.end());
//示例选项(可以是任何正整数)
int-choice1=3;
int-choice2=4;
选择的整数=5;
int number_of_choice2s=1;
向量选择;
对于(inti=0;i
然后我保留了一个迭代器来选择
,每当我需要一个新的迭代器时,我就增加迭代器并获取该值


这是可行的,但似乎有一种更有效的方法。因为我总是知道我将使用多少个值,我想知道是否有一种更为算法化的方法来实现这一点,而不仅仅是存储这些值。

您不必要地使用了这么多内存。您有两个变量:

int number_of_choice1s = 5;
int number_of_choice2s = 1;
现在只需随机化:

int result = rand() % (number_of_choice1s + number_of_choice2s);
if(result < number_of_choice1s) {
  --number_of_choice1s;
  return choice1;
} else {
  --number_of_choice2s;
  return choice2;
}
int result=rand()%(选择1的数量+选择2的数量);
如果(结果<选择的数量){
--选择的数量;
返回选项1;
}否则{
--选择2的数量;
返回选择2;
}

这可以很好地扩展两百万次随机调用。

您可以更简单地编写:

std::vector<int> choices(number_of_choice1s, choice1);
choices.resize(number_of_choice1s + number_of_choice2s, choice2);
std::random_shuffle(choices.begin(), choices.end());
std::向量选择(选择1的数量,选择1);
选项。调整大小(选项1的数量+选项2的数量,选项2);
std::random_shuffle(choices.begin(),choices.end());

有偏随机分布将在结果集上保持某种顺序(最多选择的选项下一个选择的机会越来越小),这会产生有偏结果(特别是,如果您必须选择第一个值的时间比选择第二个值的时间长,那么您将得到类似于{1,1,1,2,1,1,1,1,2}的结果

下面是代码,它看起来很像@Tomasz Nurkiewicz编写的代码,但是使用了一个简单的偶数/奇数,这应该给大约50/50的机会选择任意一个值

int result = rand();

if ( result & 1  &&  number_of_choice1s > 0)
{
number_of_choice1s--;
return choice1;
}else if (number_of_choice2s>0)
{
number_of_choice2s--;
return choice2;
}
else
{
return -1;
}

我会坚持使用有效的解决方案,除非有充分的理由不这样做。它被描述为瓶颈或类似的东西吗?有一种方法,但它会变得不那么清晰和简洁。我会坚持使用这种技术。我真的很喜欢这个解决方案。我想到的所有其他解决方案(思考大约5秒钟后)涉及随机数生成器。但由于每个选择都有一个预先确定的数目,这些解决方案将是无效的,因为它们最终将不得不在其选择已经出现最大次数后开始忽略值。(无可否认,shuffle方法可能会消耗CPU,但至少可以让它成为一个可预测的运行时间,这是我在上面考虑的解决方案所无法做到的)shuffle方法可以用O(n)完成复杂度,这是你能达到的最小值,因为你必须生成n个元素。一旦任何一个计数器达到0,你就可以短路剩下的进程。有偏差吗?这看起来就像是Knuth的从n中选择m算法的定制版本-+1从Me中选择,但请注意,如果你的标准库恰好有一个坏的
随机数
实现(例如,线性同余和小模数),像这样使用
%
会引入偏差。此外,
RAND_MAX
可能小到32767(Microsoft标准库中的
RAND
具有此属性),如果有大量选择,您将完全失败。(为免生疑问,我确实认为这是一个好办法。)你不能用
%
/
生成一个无偏选择,除非选择的数量平均分为
RAND\u MAX+1
。StackOverflow上有很多关于无偏生成随机选择的帖子。但我不确定这有多重要,因为选择的数量在不断变化。