【发布时间】:2021-12-03 21:38:42
【问题描述】:
我经常听说,如果你想要一个均匀分布,你永远不应该修改你的随机数生成器的结果。但是,我发现使用 std::uniform_int_distribution 对非常小的范围没有任何影响。
以下是使用 mod 和 uniform_int_distribution 值 0 - 15 的示例:
std::mt19937 gen;
gen.seed(0);
int ROWS = 6;
int COLS = 10;
std::cout << "mod: \n";
for (size_t i = 0; i < ROWS; ++i){
for (size_t j = 0; j < COLS; ++j){
std::cout << std::setw(2) << gen() % 16 << " ";
}
std::cout << "\n";
}
std::cout << "\n";
gen.seed(0);
std::uniform_int_distribution<> distrib(0, 15);
std::cout << "dist: \n";
for (size_t i = 0; i < ROWS; ++i){
for (size_t j = 0; j < COLS; ++j){
std::cout << std::setw(2) << distrib(gen) << " ";
}
std::cout << "\n";
}
结果:
mod:
12 15 5 0 3 11 3 7 9 3
5 2 4 7 6 8 8 12 10 1
6 7 7 14 8 1 5 9 13 8
9 4 3 0 3 5 14 15 15 0
2 3 8 1 3 13 3 3 14 7
0 1 9 9 15 0 15 10 4 7
dist:
12 15 5 0 3 11 3 7 9 3
5 2 4 7 6 8 8 12 10 1
6 7 7 14 8 1 5 9 13 8
9 4 3 0 3 5 14 15 15 0
2 3 8 1 3 13 3 3 14 7
0 1 9 9 15 0 15 10 4 7
我猜它与 2 个字节有关?我只是想知道这在数学上是如何有效的,因为它逐步通过随机数生成器和修改结果。如果范围足够小,这是否意味着 mod 会创建均匀分布?为什么是 2 字节范围而不是更多?
【问题讨论】:
-
通常情况下,至少我还没有看到不是这样的实现,
[0, RAND_MAX]的域是2的倍数。16也是2的倍数,因此用它修改rand的结果应该保持分布。尝试使用非 2 的倍数,看看是否会得到不同的结果。 -
您的测试不足以评价均匀分布。尝试数十亿个样本。
-
这里的第一个问题是“我经常听到”。从谁?在哪里?需要引用!另外,你用这些数字做什么?如果您需要它们进行密码学,那么好吧,其他假设适用。
-
@NathanOliver 更像是“尝试使用 2 的非
multiple幂”
标签: c++ random distribution mersenne-twister uniform-distribution