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

时间:2014-10-13 20:42:31

标签: c random concurrency

我是C编程的新手,我已经读过,对于线程安全的随机数生成来说,erand48()是一个不错的选择。但是该函数采用的种子值为:unsigned short int array [3]

有关应将此种子值初始化为什么的任何建议?

3 个答案:

答案 0 :(得分:2)

好的。首先,让我明确指出libc中的PRNG是确定性的(这就是为什么它需要种子),使用LCG - 这意味着它很容易预测所有一旦你有一些价值观,因此是不安全的。

现在。 erand48()从伪随机实数的均匀分布返回double大小的随机浮点值。它本身并不取种子值,而是要求您提供状态缓冲区。这是完整的声明:

double erand48(unsigned short xsubi[3]);

有趣的是,状态缓冲区必须以随机值播种,以便生成器工作。我的第一个想法是从/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;
}

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

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

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

答案 1 :(得分:1)

只是我的2美分......

我们之前的一个项目中使用了相同的函数系列。该产品必须在Windows / Unix上运行,因此我们没有使用 / dev / random

相反,我们将 host_ip_addr + time()+ process_id + thread_id 连接成一个字符串,并从该字符串生成一个哈希值。然后,我们将尾随字节XOR传送到6个前导字节。我们用最终数据作为种子...

答案 2 :(得分:0)

rand48系列是48位LCG,意思是

double erand48(uint48_t *state) {
    *state = *state * A + C;             /* A and C are suitable values */
    return *state / 281474976710656.0;   /* that's 2^48 */
}

...除了我从未见过具有uint48_t的计算机,所以你传递的是一个48位状态的数组(3x16假设一个短的16位)。 你可以用任何东西播种它 - 只需获得48个随机位并将它们从/ dev / urandom中推送到数组[3]中,从时间/ pid /中提取。

一些陷阱: - lcong48() - 忘了它甚至存在 - &#34;我怎样才能确保两颗种子彼此之间并不可笑呢?&#34; - 不要,只需使用另一个rng就可以花更少的时间。