执行随机for循环并每次保存随机值

时间:2015-03-23 16:55:56

标签: c++

我想选择一个集合的随机部分(例如,用于排除某些随机值的正常for循环)并且每次都存储排除的值。

循环中的这个简短示例:

for (int i=0; i<20; i++){

//test1

do smthing with the i's between 0-19 except (3 and 14)

//test2

do smthing with the i's between 0-19 except (0 and 1)

//test3

do smthing with the i's between 0-19 except (19 and 5)
...

//testn

do smthing with the i's between 0-19 except (...)

}

`

我希望“除了部分”在每一步都不同,将其存储在矢量中,并能够定义避免的点数。

是否有最简单的方法可以在C ++中实现这一目标。

我在网上找到了这个功能,但仅限于一点:

// Generate a random number between nLow and nHigh (inclusive)
unsigned int GetRandomNumber(int nLow, int nHigh)
{
return (rand() % (nHigh - nLow + 1)) + nLow;
}

在实践中,循环有5844步,排除了854。我向我提出了以下代码:

for(int test = 0; test < 5844; test++)
int exclude[854];
exclude[0] = rand()%5844;
exclude[1] = rand()%5844;
.
.
.
exclude[854] = rand()%5844; //(but too long even with a loop)
for(int i = 0; i < 5844; i++) {
if(i == exclude[0] || i == exclude[1] || ...||i == exclude[854]) continue;
// do work...
}
}

感谢。

2 个答案:

答案 0 :(得分:0)

实际上,多个被排除的数字可能具有相同的价值。您可以使用C ++ 11的一些新random功能来确保所有数字都不同。这是一个可能的解决方案,使用std::shuffle;这可能会被优化,但除非运行时间太长,否则没有理由这样做:

#include <iostream>  // std::cout
#include <algorithm> // std::shuffle
#include <vector>    // std::vector
#include <numeric>   // std::iota
#include <random>

std::default_random_engine rng{std::random_device{}()};

int main()
{
    // Our initial set [0-5843]
    std::vector<int> vec(5844);
    std::iota(vec.begin(), vec.end(), 0);

    // Take a random subset of 854 elements
    const int exclude{854};
    std::shuffle(vec.begin(), vec.end(), rng);
    std::vector<int> excluded(vec.end()-exclude, vec.end());
    vec.erase(vec.end()-exclude, vec.end());

    std::cout << "Do work for " << vec.size() << " elements.\n";
    for (int i : vec) {
        // Do work...
    }

    std::cout << "Excluded " << excluded.size() << " elements.\n";

    return 0;
}

请注意,这会更改迭代的顺序。例如,在开展工作时,i = 100可能会在i = 10之前执行。

Live Demo

答案 1 :(得分:0)

我们知道有多少有效数字,所以首先选择该范围内的数字:

static std::mt19937 gen(std::random_device{}());
std::uniform_int_distribution<> dis(nLow, nHigh-ignored.size());
unsigned value = dis(gen);

然后,对于每个小于或等于我们选择的无效数字,我们必须将该值增加一。幸运的是,这是一项微不足道的操作。 (注意:ignored值必须按递增顺序排序)

auto it = std::upper_bound(ignored.begin(), ignored.end(), value);
value += it-ignored.begin();

最后, 操作可能会使我们超过几个不允许的数字,所以我们会超越这些数字,直到我们恢复正常为止。这可能会使我们超越其他人,所以这在逻辑上是棘手的部分,即使代码很简单。 it!=ignored.end()是一种健全性检查,应该是不可能的。

while(it != ignored.end() && *it<= value) {
    ++it;
    ++value;
}

那就是它!你可以在这里看到它:http://coliru.stacked-crooked.com/a/28b40f978a90216c