我想从 [1,10] 中大量绘制 1 个整数,然后检查每个整数出现的次数。我写了这段代码,它正在编译但显示分段错误。你能指出问题出在哪里吗?
#include <iostream>
#include <random>
#include <array>
int main(){
std::random_device rd;
std::mt19937 dre(rd());
std::uniform_int_distribution <int> di(1,10);
std::array<int,10> count{0};
for(int i=0;i<10000;++i)
{
int rand=di(dre);
count[rand]++;
}
for (int foo: count){
count[foo]/=10000;
std::cout << foo << " " << count[foo] << std::endl;
}
}
如果你定义一个由 10 个元素组成的数组,就像你在这里所做的那样:
std::array<int,10> count{0};
然后数组将具有索引 0-9。所以count
的范围从count[0]
到count[9]
不等。
但是,在这里:
count[rand]++;
当rand
为 10 时,您正在尝试访问不存在的count [10]
。
为了回答编辑中的后续问题,您需要循环并创建10000
随机数,如下所示:
for(int i=0;i<10000;++i)
{
int rand=di(dre);
当您在 10 个不同的数字之间进行选择时,您会期望每个数字的计数约为 1000,并且分布均匀。
但是,当您打印结果时,将每个计数除以 10000:
count[foo]/=10000;
因此,这意味着现在每个计数很可能约为 0.1。当您将其存储在整数中时,它会向下舍入为零。
你调用count[rand]
其中计数有 10 个项目,这意味着索引在 0..9 范围内,但 rand 在 1..10 范围内,所以每隔一段时间它就会调用count[10]
这会导致你的 seg 错误。
使分布改为使用 [0..9]:std::uniform_int_distribution <int> di(0,9);
对于for (int foo: count)
,foo
依次等于count
中的每个元素。您需要在循环中单独使用 foo
而不是 count[foo]
,或者如果您需要索引,请使用显式for
循环。
此外,std::uniform_int_distribution
是包含边界的,因此您需要使用 0, 9
而不是1, 10
来初始化它以索引到您的十元素count
中。
您的均匀分布应定义为:
std::uniform_int_distribution <int> di(0, 9);
因为您的数组元素是从 0
索引到 9
的。按原样,您的rand
变量最终将大于9
此时您正在越界读取,从而导致未定义的行为。即使rand
保持在边界内,基于范围的循环for
也会显示UB,因为foo
存在实际数组元素的值,但尚未用作索引。应改为通过引用传递:
for (int& foo : count) {
foo /= 10000;
std::cout << foo << 'n';
}
此外,如果您使用的是 C++11,那么您将需要此处的 std::array 初始值设定项的双大括号:
std::array<int, 10> count{ { 0 } };