c:使用 PCG 实现生成随机数

标签 c random

我正在尝试在 c 中实现 PCG 随机数生成器。因为我是 c 的初学者,所以我很难理解这些例子。到目前为止,我尝试实现可以​​找到的最小版本 here .

这是我的代码,现在可以生成一些(希望如此)伪随机数:

#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 语言中获得良好的伪随机数,该方法适用于代码的每个部分?

最佳答案

在不知道您使用的实现的情况下,查看这些行:

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() 示例实现,用于 0x7fffffffRAND_MAX >,这可能有助于更好地理解 PRNG 的一般概念:

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() 的结果

关于c:使用 PCG 实现生成随机数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47137488/

相关文章:

c - 在套接字中使用 read() 访问缓冲区

c - 我的字数统计程序出了什么问题?

c - 我不明白如何在简单计算器中输入或划分 float 和 int

c - 在 C 编程中反转数组元素

java - 正确生成随机数

r - 蒙特卡洛积分不起作用?

c - GTKSDL - 处理事件

mysql - 如何从大表的子集中选择mysql中的n个随机行?

java - Java 中的随机化

Rcpp - 加速 for 和 while 循环内的随机正常绘制