我想选择一个集合的随机部分(例如,用于排除某些随机值的正常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...
}
}
感谢。
答案 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
之前执行。
答案 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