我正试图用c语言实现PCG随机数生成器。由于我是c ++的初学者,所以我很难理解这些例子。到目前为止,我尝试实现可以找到这里的最小版本。
下面是我的代码,它现在产生了一些(希望是)伪随机数:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>
#include <math.h>
#include "pcg_basic.h"
int main(int argc, char** argv){
pcg32_random_t rngptr;
pcg32_srandom_r(&rngptr, time(NULL), (intptr_t)&rngptr);
for (int round = 1; round <= 10; ++round) {
printf(" %f\n", ldexp(pcg32_random_r(&rngptr) ,-32));
}
return 0;
}
这是一个很好的实施,还是可以更好地改进?
问题是:我想在代码中的任何地方使用随机数,而不仅仅是在main()
函数中。我该怎么做?我试过:
double myrand(){
pcg32_random_t rngptr;
pcg32_srandom_r(&rngptr, time(NULL), (intptr_t)&rngptr);
return ldexp(pcg32_random_r(&rngptr) ,-32);
}
然而,这种方法不起作用,在我看来是不对的。但我不知道如何做得更好。
有人能告诉我一个简单的方法,在c中得到好的伪随机数,这在代码的每个部分都是有效的吗?
发布于 2017-11-06 13:14:58
在不知道您使用的实现的情况下,查看以下行:
double myrand(){
pcg32_random_t rngptr;
pcg32_srandom_r(&rngptr, time(NULL), (intptr_t)&rngptr);
return ldexp(pcg32_random_r(&rngptr) ,-32);
}
第二行种子随机数发生器。每次调用这样做都会使实际的PRNG无效。
每个PRNG的工作方式是保持一些内部状态,并使用一些或多或少复杂的算术操作来计算前一个状态的下一个状态。然后将内部状态的一部分作为下一个“随机”数返回。
由于内部状态必须从某个地方开始,所以必须准确地为每个PRNG注入种子(并使用类似于time()
的方法,以便在每次运行时都在不同的地方启动)。
因此,这段代码的简单版本如下所示:
double myrand(){
static int initialized = 0;
static pcg32_random_t rngptr;
if (!initialized)
{
pcg32_srandom_r(&rngptr, time(NULL), (intptr_t)&rngptr);
initialized = 1;
}
return ldexp(pcg32_random_r(&rngptr) ,-32);
}
这不再是线程安全的,因为整个程序中只有一个PRNG实例(由pcg32_random_t
变量表示)。
另一种方法是让您的函数实际获得指向PRNG的指针,并在外部管理创建和播种(例如,在main()
中一次):
double myrand(pcg32_random_t *rngptr){
return ldexp(pcg32_random_r(rngptr) ,-32);
}
int main(void)
{
// do this once:
pcg32_random_t rngptr;
pcg32_srandom_r(&rngptr, time(NULL), (intptr_t)&rngptr);
// [...]
double x = myrand(&rngptr);
}
C标准函数srand()
和rand()
也是如此:您必须精确地调用srand()
一次才能启动PRNG。使用这些函数,内部状态是static
(在C标准库中),因此您不必传递任何内容,而且使用这些函数也不是线程安全的。
下面是一个非常简单而愚蠢的实现标准C rand()
的RAND_MAX
of 0x7fffffff
的例子,它可能有助于更好地理解0x7fffffff
的一般概念:
static unsigned long long int randval = 1;
void srand(unsigned int seed)
{
randval = seed;
}
int rand(void)
{
randval *= 1103515245;
randval += 12345;
return (int)((randval / 65536) & 0x7fffffff);
}
正如您所看到的,randval
是保密的,但是调用srand()
会设置它,因此会影响下一个对rand()
的调用的结果。
https://stackoverflow.com/questions/47137488
复制相似问题