c++ - 在 C++ 中生成随机字符串的最有效方法是什么?
问题描述
我需要有效地生成随机字符串。在下文中,您将看到我的第一次尝试。我用 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);
}
我检查std::sample
了c++17,它并不比上述方法快。此外,它不会改变字符的顺序,所以它不是真正的随机。
编辑:这std::shuffle
不是一个好的选择,因为它不允许重复。根据评论,我修改了代码。这次 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++ 中是否有更有效的方法来做到这一点?
我感谢任何改进代码的建议。
解决方案
#include <iostream>
#include <random>
#include <algorithm>
#include <chrono>
std::string chars {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()`~-_=+[{]{|;:'\",<.>/?"};
std::random_device rd;
std::mt19937 generator(rd());
std::string rand_str(int length) {
std::string output;
output.reserve(length);
while(length>0)
{
auto randNumb = generator();
while(randNumb > 93 && length--)
{
output.push_back(chars[randNumb%93]);
randNumb/=93;
}
}
return output;
}
int main() {
auto startTP = std::chrono::system_clock::now();
std::string rand_bytes;
for (long i=0; i<10000000; ++i)
rand_bytes = std::move(rand_str(64));
auto endTP = std::chrono::system_clock::now();
std::cout << "This took: " << std::chrono::duration_cast<std::chrono::microseconds>(endTP-startTP).count() << std::endl;
}
这在我的机器上大约需要 3 秒。诀窍是尽可能少地调用随机数生成器并且只分配一次内存。
我正在做的是将 randNumber 从基数 10 转换为基数 93(字符的长度)。之后,我使用每个基数 93 位作为不同的随机数。这为每个生成的随机数提供了大约 5 个数字。
推荐阅读
- c# - 如何在页面加载时显示选取器而不点击标题 Xamarin.Forms
- wso2 - 使用 SIddhi Execution Json API 从文本中提取 json
- javascript - 简单的 ES6 属性调用超出了最大调用堆栈大小
- python - Django HStoreField 来自 shell 的不同输出
- facebook - 对于带有注册/登录链接的网络电子邮件身份验证 - 哪个是 FB Account Kit 的最佳替代品?Twilio 或 Firebase 之类的?
- python - 如何在 python pandas 中的数据帧上执行 groupby 时保留带有空(nan)单元格的行
- javascript - 如何使用锚标记上的 javascript 下载从 Sharepoint 列表中获取的 excel 表
- apache-spark - Spark SQL、pyspark中可以使用SQL递归吗?
- python - 从消息中获取关键字
- android - 下载管理器有时显示不成功