【问题标题】:C++11 Random between int x, int y, excluding list<int>C++11 int x, int y 之间的随机,不包括 list<int>
【发布时间】:2014-11-10 20:38:42
【问题描述】:

我需要一种在 x,y 之间生成随机整数的方法,但是一旦生成了随机 z,我需要 x,y 的下一次迭代来排除 z(或者更好的是,要排除的整数列表)。返回值必须遵守“std::uniform_int_distribution”条件。有一种明显的方法可以做到这一点,但我希望有一个快速的版本。

int GenerateRandomBetweenExcluding(int min, int max, int exclude) // even better is a list<int> to exclude
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(min, max); // how to exclude "exclude" or list<int>?

    int randNum = dis(gen);

    return randNum;
}

【问题讨论】:

  • minmax-1之间随机化如果结果>=exclude,加一个
  • 这会改变分布的均匀性,因为返回值可能会超出排除范围。
  • 如果你不想重复,maby std::random_shuffle 很有帮助
  • 如果您开始防止重复,我很难理解它如何仍然是均匀分布。
  • 完全旁注:std::list 可能是使用错误的容器。

标签: c++ c++11 boost random std


【解决方案1】:
#include <algorithm>
#include <vector>
#include <random>

class NoRepeat
{
public:
    void Init(int,int);
    int GetOne();
    bool HasMore();
private:
    std::vector<int> list;
};

void NoRepeat::Init(int min, int max) // min and max are inclusive
{
    list.clear();
    list.reserve(max-min+1);
    for( int i=min; i<=max; ++i )
        list.push_back(i);
    std::random_shuffle( list.begin(), list.end() );
    // might want to supply own random_func, default uses rand()
}

bool NoRepeat::HasMore()
{
    return !list.empty();
}

int NoRepeat::GetOne()
{
    int ret = list.back();
    list.pop_back();
    return ret;
}

【讨论】:

  • -1 因为只有代码的答案。请考虑解释或展示一种可能的方法,而不是 “plz send teh codez” 之类的答案
【解决方案2】:

使用包含最小值和最大值之间的所有数字的列表。随机选择一个元素并删除它。

【讨论】:

  • @JBL “所以你正在寻找一个没有重复的随机样本,对吗?” - 这是一种方法。
  • 如果可能的数字列表很大怎么办?
  • 您可以省略列表中的所有元素。问题是关于整数,但你想排除类型 T 元素?
  • T 部分是错字。固定
【解决方案3】:

如果您的排除列表按升序排序,这是一种很好的方法。您可以通过使用set&lt;int&gt; 而不是list&lt;int&gt; 来跟踪排除项来实现此排序;大多数集合操作需要log(n) 时间,并且保证容器始终被排序。

算法如下:

set<int> exclude;
/* ... configure generator and exclusion set ... */
uniform_int_distribution<> dis(min, max-exclude.size());
int val = dis(gen);

/* skip over the exclusions */
for(int i : exclude) {
    if(val >= i) val++;
    else break;
}
return val;

【讨论】:

    猜你喜欢
    • 2013-01-26
    • 1970-01-01
    • 2012-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-05
    • 1970-01-01
    相关资源
    最近更新 更多