在注意到rand()函数每次产生41的相同输出后,我使用srand(time(0))播种了生成器。这解决了重复输出的问题,但现在它给了我不断增加的数字。 (I.E. 245,248,250,253,255,256)。我可以理解,由于系统时间的影响,它正在增加,但这是正常的吗?
这是我的计划:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
int number;
srand(time(0));
cout << rand() % 1000;
return 0;
}
我反复运行这个而不是循环。 多次试验的输出: 285 295 305 311 325 334 344 354 355
答案 0 :(得分:5)
来自MS的C ++ rand()
使用最简单的随机生成器Linear congruential generator
这是它的代码:
int __cdecl rand (
void
)
{
_ptiddata ptd = _getptd();
return( ((ptd->_holdrand = ptd->_holdrand * 214013L
+ 2531011L) >> 16) & 0x7fff );
}
因此,每当你为你的函数设定种子时,你只需设置第一个值(如果你快速运行你的程序,它会不时地增加一些单位)
现在,如果您插入rand()
值x+a
的数学等式,其中x
是上次调用函数的值,而a
是自那次通话以来你的时间变化你会注意到:
((x + a)* 214013 + 2531011)&gt;&gt; 16 =(x * 214013 + 2531011 + a * 214013)&gt; 16
因为您运行程序的速度非常快。您的a
在0
和5
秒之间变化,让我们说。那么,当你将这个数字右移16位时,a*214013
的最大值为1070065
,最后得到的是16
十进制数,这是近似很多你的新输出与你以前的输出不同(我说大约是因为你不能说(x * 214013 + 2531011 + a * 214013)&gt;&gt; 16 =(x * 214013 + 2531011&gt;&gt; 16)+( a * 214013&gt;&gt; 16)因为携带而来)
答案 1 :(得分:3)
这个错误每周大约出现一次:
如果您在调用rand()之前每次都致电srand()
,那么您根本不会获得随机数,您将获得当时的哈希函数。在循环外调用srand()
ONCE,ON ON ONCE,最好是在程序的最开始,然后根据需要多次调用rand()
来获取值。
没有生成&#34;一个随机数&#34;。如果在一系列程序调用中需要随机数,则别无选择,只能在程序外生成这些随机数。一种方法是从/dev/urandom
(在Linux上)或使用CryptGenRandom
(在Windows上)读取。另一种选择是使用硬件或random.org
等服务。
你拥有的发电机有多重要 - 如果你为每一次通话播种,你没有得到随机数,你就会获得种子值的哈希函数。如果您的种子值变化足够快,并且散列函数非常好,那可能已经足够好了 - 但它仍然没有使用RNG算法。
答案 2 :(得分:1)
我不知道你为什么会得到这些结果,但在C ++ 11中有更好的方法:
#include <random>
#include <iostream>
int main()
{
auto rnd = std::default_random_engine(std::random_device{}());
std::uniform_int_distribution<> dis(1, 999);
std::cout << dis(rnd) << '\n';
}
答案 3 :(得分:0)
rand
的工作方式是您需要遵循两条规则:
srand
)和rand
之前播种它。你只需要在整个序列之前播种一次。所以为了真正测试你,你的代码看起来应该更像这样:
int main()
{
srand(time(0));
// Output a sequence of 100 random numbers, each less than 1000
for ( int i = 0; i < 100; i++ )
cout << rand() % 1000 << endl;
return 0;
}
如果程序必要时每次运行仅输出一个随机数,并且程序每秒运行一次或多次,那么time(0)
可能不是合适的种子。也许使用clock_gettime(3)
会在几毫秒内为您提供更多内容。
答案 4 :(得分:0)
rand
在运行时库中实现为线性同余生成器,其形式如下:
result = (seed * result + offset) % big_number
如果我们认为big_number
是无限的并且您在t
时间运行您的程序,那么
result = t * result + offset
如果您在很短的时间alpha
之后再次运行该程序,那么
result = (t + alpha)* result + offset
如果运行时库使用较小的值初始化结果,则显示的结果将以alpha * result
的小值递增。
用更高分辨率的计数器替换time()
会大大改善这一点。例如,在x86上,rdtcs
指令(通常作为编译器内部提供)几乎可以解决问题。
更好的解决方案是使用非线性同余生成器来种子rand()
,就像Jesse Good建议的那样,也可以通过boost库在非c ++ 11编译器上使用。
如果可能的话,最好坚持使用c ++ 11随机生成器而不是c rand。
答案 5 :(得分:0)
我最近碰到了同样的问题,发现Karoly Horvath对你原来问题的评论解决了这个问题,虽然它有点“hacky”。我看到返回值有可预测的增加,并且在rand()
之后立即粘贴另一个srand()
后,问题就消失了。我最终得到了这个:
srand(time(NULL));
rand();
int seed = rand();
我想弄清楚为什么这种情况发生了......但与此同时这很有效。