我应该为 C 中的 erand48() 使用什么种子值?

Ger*_*ang 5 c random concurrency

我是 C 编程新手,我读到 erand48() 是线程安全随机数生成的一个不错的选择。然而,该函数采用的种子值为:unsigned Short int array[3]

关于这个种子值应该初始化为什么有什么建议吗?

han*_*rak 3

好吧。首先,让我明确一点,PRNG 是libc确定性的(这就是它需要种子的原因),使用 LCG -这意味着一旦有一些值就很容易预测所有值,因此是不安全的。

接着。从伪随机实数的均匀分布中erand48()返回大小的随机浮点值。double它本身不需要种子值,而是需要您提供状态缓冲区。以下是完整的声明:

double erand48(unsigned short xsubi[3]);
Run Code Online (Sandbox Code Playgroud)

有趣的是,状态缓冲区必须以随机值作为种子才能使生成器工作。我的第一个想法是阅读/dev/urandom

我们可以用这样的方法来做到这一点(使用无缓冲读取来防止这种小读取造成的浪费):

#include <stdio.h>
#include <stdlib.h>

void *thread_f (void *i) {
    // setup unbuffered urandom
    urandom = fopen ("/dev/urandom", "r");
    setvbuf (urandom, NULL, _IONBF, 0);  // turn off buffering

    // setup state buffer
    unsigned short randstate[3];
    // fgetc() returns a `char`, we need to fill a `short`
    randstate[0] = (fgetc (urandom) << 8) | fgetc (urandom);
    randstate[1] = (fgetc (urandom) << 8) | fgetc (urandom);
    randstate[2] = (fgetc (urandom) << 8) | fgetc (urandom);


    // cleanup urandom
    fclose (urandom);

    // you can now use erand48 (randstate);

    ...     // do whatever work you need to do

    return result;
}
Run Code Online (Sandbox Code Playgroud)

这是线程安全的,甚至可以确保所有线程的种子值相对安全。

当然,如果速度不是太大的问题(即:您可以忍受速度的小损失)并且您可以接受整数,那么直接进行无缓冲读取/dev/urandom是一个完美的解决方案。更好的是,/dev/urandom 提供安全、不可预测的伪随机整数(从技术上讲,是字节流,但只要匹配大小,它们就始终以整数形式工作),这些整数通常也是均匀分布的。

另外,/dev/urandom定期将熵注入其中并刷新,确保您拥有足够的相当随机的数字。