没有腹肌的八宝粥 · 使用命令行发布 Android 应用 - ...· 4 月前 · |
潇洒的蚂蚁 · laravel 模型打印sql-掘金· 1 年前 · |
大鼻子的骆驼 · TS中的类型 - 知乎· 1 年前 · |
乐观的冰棍 · Day27 Video.js + ...· 1 年前 · |
我有一个函数从一组字母表中生成随机字符。这个函数将被多次调用,因此我试图让它使用相同的变量集,即具有相同的种子,这样字符串就不会重复尽可能长的时间。
#include <iostream>
#include <random>
#include <string>
std::string generateRandomChar(const unsigned int _len)
std::string result;
result.reserve(_len);
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 61);
for (int i = 0; i < _len;
result += (alphanum[dis(gen)]);
return result;
int main(){
for(int i = 0; i < 10; ++i){
std::cout << generateRandomChar(10) << std::endl;
}
不幸的是,我对C++11
<random>
函数没有任何专门知识,而且我之前只使用了
srand
和朋友,所以我在这里可能会犯很多错误。目前,它不重复地工作并生成大量字符串,但我确信我可以做到以下两种:
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 61);
静态变量也是如此,所以每次调用函数时都不会计算它,因为这会浪费时间,对吗?
那么哪一个应该是静态的呢?你在这里看到了什么错误/改进吗?
发布于 2018-10-26 20:18:03
无论您放在哪里,
static
都会极大地改变您的程序的行为。最后,我们有了
2^3 = 8
组合,所以让我们检查其中的一些。
如果没有用于随机数的硬件设备,
random_device
可能会退回到伪随机引擎。如果在本例中不对
static
使用
random_device
,则所有字符串都可能以相同的方式结束,因为伪随机引擎可能会使用定义的固定种子来初始化。
std::random_device a;
std::random_device b;
assert(a() == b()); // worst case if no hardware-device or a low-effort implementation is used
在这种情况下,
mt19937
将始终以相同的值作为种子,我们在每次调用中都会得到相同的字符串。如果
mt19937
或
random_device
是静态的,这种情况就会改变,如果
dist
是静态的,则可能会改变,因为
uniform_int_distribution
可以使用几次对生成器的内部状态调用。
当然,如果
mt19937
是静态的,那么您也可以将
random_device
更改为
static
变体,因为它只需要计算一次。这是您在程序开始时最接近单个
srand()
调用的地方。但是,您的
uniform_int_distribution
仍然失去了它的内部状态。
最后,这取决于我们是否希望两个
generateRandomChar
调用相互关联。如果它们根本不相关,我们需要用一个新的非确定数重新分配我们的PRNG,并且根本不能使用
static
。
或者,换一种说法:如果我们对所有三个值都使用
static
,那么
generateRandomChar(10) + generateRandomChar(10)
与generateRandomChar(20)相同--如果我们在
mt19937
上使用
static
,那么两者可能是相同的,这取决于
_len
和
dist
。
无论哪种方式,如果您希望对生成有更多的控制,您只需在您的函数中提供一个生成器:
template <typename Generator>
std::string generateRandomChar(Generator & gen, const unsigned int _len)
}
分配的情况也是一样。
除此之外,我将使用
sizeof
而不是
61
来确保在不更改
dist
's构造函数中的数字界的情况下,不会意外地更改可能的字符池:
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, sizeof(alphanum) - 1);
发布于 2016-09-21 18:35:37
我认为您应该为此创建一个单独的包装类。我使用了以下方法:
#include <random>
class randomStreamUniformInt {
public:
explicit randomStreamUniformInt(int lower_bound, int upper_bound)
: mt(rand()), uniform_dist(lower_bound, upper_bound) {}
explicit randomStreamUniformInt(int lower_bound, int upper_bound, double seed)
: mt(seed), uniform_dist(lower_bound, upper_bound) {}