【发布时间】:2020-12-01 02:37:34
【问题描述】:
我需要有效地生成随机字符串。在下文中,您将看到我的第一次尝试。我用 gcc 和 -O3 优化级别编译了代码。生成 10^7 个长度为 64 的随机字符串需要 18.5 秒:
#include <iostream>
#include <random>
#include <algorithm>
std::string chars {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()`~-_=+[{]{|;:'\",<.>/?"};
std::random_device rd;
std::mt19937 generator(rd());
std::string rand_str (int length) {
std::string output (chars);
std::shuffle(output.begin(), output.end(), generator);
return output.substr(0, length);
}
int main() {
std::string str;
for (long i=0; i<10000000; ++i)
str = rand_str (64);
}
我在 c++17 中检查了std::sample,它并不比上述方法快。另外,它不会改变字符的顺序,所以不是真正的随机。
编辑:std::shuffle 不是一个好的选择,因为它不允许重复。基于 cmets 我修改了代码。这次 10^7 个随机数需要 9 分钟。
std::string rand_str (size_t length) {
const size_t char_size = chars.size();
std::uniform_int_distribution<> random_int (0, char_size - 1);
std::string output;
for (size_t i=0; i<length; ++i)
output.push_back(chars[random_int(generator)]);
return output;
}
问题
- 在现代 C++ 中是否有更有效的方法来做到这一点?
感谢任何改进代码的建议。
【问题讨论】:
-
首先,你不说随机字符串的要求。根据您的代码,要求是每个随机字符串不能有重复的字符。
-
std::mt19937具有相对较好的 PRNG“质量”,但也不是超快。有更快的 PRNG,例如Xorshift。 -
另一个观察结果:1)您的代码没有可观察到的效果,因此编译器可能会将其完全优化为
return 0;inmain。 2)每次迭代都有分配,这是不必要的。 -
如果您不想重复,则使用从
0到大小为chars的随机数生成器,然后使用该随机生成器的数字进行chars[random_number]访问可能会更快。 -
生成随机数的速度比您预期的要慢得多。它很容易成为门控因素。