我使用rand()进行两次整数,介于0和2之间。看来第一个int从不为0而第二个int是2.这是我的测试代码 -
#include <iostream>
#include <time.h>
int main()
{
srand(time(NULL));
int number1, number2;
number1 = rand() % 3;
number2 = rand() % 3;
printf("%i, %i", number1, number2);
return 0;
}
输出-25次尝试
2, 2
2, 2
2, 1
1, 2
0, 1
2, 2
1, 2
1, 0
2, 1
1, 0
0, 0
1, 2
2, 2
0, 0
2, 1
1, 0
2, 2
1, 0
2, 1
1, 0
0, 1
1, 2
1, 0
0, 0
2, 2
正如你所看到的,在25次尝试中,组合从未为0,2。这是我应该转移到的标志吗?随机&gt;?此外,永远不会有2,0。
答案 0 :(得分:3)
不,这将发生在所有种子的9 *(1-1 / 9)^ 25 = 0.4736,或大约50%的时间。也就是说,你的前25个结果中将缺少{0,1,2}中带有数字的两位数序列,大约是运行程序的一半。
再次运行它,看看会发生什么。
答案 1 :(得分:2)
您一定要使用<random>
。你越早忘记rand
的存在,你就越幸福。
rand
有时会使用linear congruential generator(LCG)来实施。 LCG遭受许多缺陷,最相关的是顺序生成的数字的低阶位高度相关。因此,您不应使用rand() % k
生成[0, k)
范围内的数字。还有其他原因。实际上,从限制范围生成无偏随机整数涉及一些细微之处,<random>
为您处理。
srand(time(NULL))
将随机数生成器播种到当前时间(以秒为单位),这意味着如果您按顺序多次运行程序,则种子将相同或相似。如果种子相同,则随机数序列也将相同。如果种子相似,则随机数序列也可以是相似的。除非在长期运行的程序中,否则不要这样做。为伪随机数生成器找到一个好种子可能很棘手。 <random>
实施将有更好的默认行为,因此您通常不必担心这一点。
答案 2 :(得分:1)
是的。这段代码在第一次运行时给了我0.2对:
for( int i = 0; i < 20; ++i) {
number1 = rand() % 3;
number2 = rand() % 3;
printf("%i, %i\n", number1, number2);
}
从均匀分布生成真正的随机数并不能保证给定(可能)的数字会出现在有限数量的试验中。良好PRNG的四个BSI criteria中的K2是
因此,生成伪随机数的趋势往往与从真正的随机分布中采样的方式相同 - 尽管由于限制,任何(可能的)数字将出现在某个点(时间小于或等于其周期)。K2 - 一系列与'真实无法区分的数字 根据指定的统计检验随机'数字。
除了以上rand()
不是最好的发电机。只要模运算中的除数不均匀地划分PRNG的范围,它就会始终引入偏差。运算符%使得以这种方式产生的概率分布倾斜,因为作为rand()
的最大值的RAND_MAX可能不等于k * 3 + 2.如果除数不均匀地划分范围,则分布将偏斜并且偏差增加与除数。您可以阅读here更多内容。总结一下:在C ++中你应该使用<random>
库:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 gen( rd());
std::uniform_int_distribution<> dis( 0, 2);
for ( int n = 0; n < 25; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
答案 3 :(得分:1)
取%3不依赖于低阶位。
我运行下面的程序使用VC ++模拟运行OP的程序一千万次,在调用之间一秒钟。它没有偏见。
start = 1413167398
(0, 0) 1110545
(0, 1) 1111285
(0, 2) 1111611
(1, 0) 1111317
(1, 1) 1111666
(1, 2) 1110451
(2, 0) 1111580
(2, 1) 1110491
(2, 2) 1111054
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <map>
#include <utility>
int main()
{
std::map<std::pair<int, int>, int> counter;
unsigned int start = static_cast<unsigned int>(std::time(nullptr));
std::cout << "start = " << start << std::endl;
unsigned int finish = start + 10000000;
for (unsigned int seed = start; seed != finish; ++seed)
{
std::srand(seed);
int x = rand() % 3;
int y = rand() % 3;
++counter[std::make_pair(x, y)];
}
for (auto iter = counter.cbegin(); iter != counter.cend(); ++iter)
{
std::cout << "(" << iter->first.first << ", " << iter->first.second << ") ";
std::cout << iter->second << std::endl;
}
return 0;
}