Хорошо. Поэтому прежде всего позвольте мне пояснить, что PRNG в libc
является детерминированным (вот почему он хочет семя), использует 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
Периодически в него вводится энтропия и обновляется, гарантируя, что у вас есть приличная поставка довольно случайных чисел.
Почему не то же самое, что' srand': 'time'? Поскольку у вас есть еще несколько бит для заполнения, возможно, запустите' pid' – usr2564301
@Jongware, потому что 'time' не обновляется нигде близко к тому, чтобы там была разница между потоками (1s для' libc: time', <1ms для 'pthread: create'). – haneefmubarak
@haneef: thanks Я полностью забыл про потоки, и, действительно, это возможно (если не просто * обычно *) будет создано несколько потоков в том же миллисекунде. – usr2564301