c ++ генерирует хорошее случайное начальное число для генераторов псевдослучайных чисел - PullRequest
6 голосов
/ 15 апреля 2010

Я пытаюсь создать хорошее случайное начальное число для генератора псевдослучайных чисел. Я думал, что получу мнение эксперта. дайте мне знать, если это плохой способ сделать это или есть намного лучшие способы.

#include <iostream>
#include <cstdlib>
#include <fstream>
#include <ctime>

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/random", std::ios::binary);
    if (file.is_open())
    {
        char * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = int(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    return random_seed;
} // end good_seed()

Ответы [ 7 ]

5 голосов
/ 15 апреля 2010

Код, который читает из / dev / random, кажется неправильным: вы в C-стиле преобразуете адрес вашего буфера символов в random_seed_a (здесь включен плагин для C ++) и игнорируете все, что вы фактически читаете из / dev / random (попробуйте*reinterpret_cast<int*>(memblock).

/ dev / random уже должен быть хорошим источником энтропии, поэтому, если он доступен, не стоит портить значение другими данными, а просто использовать его как начальное число напрямую. Если нетЕсли в / dev / random достаточно данных, я бы просто использовал время и использовал их сам по себе, а не хранил их чем-то.

3 голосов
/ 15 апреля 2010

Хорошие генераторы псевдослучайных чисел не нуждаются в «хорошем» семени, любое начальное число (которое отличается от запуска к запуску) работает одинаково хорошо.

Использование системного времени нормально (и распространено). Использование /dev/random тоже хорошо.

Если ваш генератор псевдослучайных чисел не хорош, даже выбор «хорошего» семени не поможет. Замените его, если можете.

Предложения: Mersenne twister довольно уважаем. Вот предшественник, который будет работать даже в самых ограниченных системах.

2 голосов
/ 15 апреля 2010

Хорошо, вот изменения, которые я сделал после рассмотрения вашего ввода. Кстати, спасибо за все!

unsigned int good_seed()
{
    unsigned int random_seed, random_seed_a, random_seed_b; 
    std::ifstream file ("/dev/urandom", std::ios::binary);
    if (file.is_open())
    {
        char * memblock;
        int size = sizeof(int);
        memblock = new char [size];
        file.read (memblock, size);
        file.close();
        random_seed_a = *reinterpret_cast<int*>(memblock);
        delete[] memblock;
    }// end if
    else
    {
        random_seed_a = 0;
    }
    random_seed_b = std::time(0);
    random_seed = random_seed_a xor random_seed_b;
    std::cout << "random_seed_a = " << random_seed_a << std::endl;
    std::cout << "random_seed_b = " << random_seed_b << std::endl;
    std::cout << " random_seed =  " << random_seed << std::endl;
    return random_seed;
} // end good_seed()
1 голос
/ 15 апреля 2010

«Хорошие» генераторы, «плохие генераторы» это ничего не значит. «Любой, кто рассматривает арифметические методы получения случайных цифр, конечно, находится в состоянии греха». - Джон фон Нейман. Каждый такой генератор - это просто детерминированный алгоритм. очень важно иметь начальные состояния (семя), которые приносят достаточно энтропии. В зависимости от того, что вам нужно, вы должны проверить качество вашего генератора. Метод Монте-Карло является очень хорошей оценкой генератора псевдослучайных чисел.

1 голос
/ 15 апреля 2010

Традиционно, мы использовали первый или второй пользовательский ввод для заполнения наших значений, поскольку время (от тиковых значений до миллисекундного диапазона), которое им требуется для ответа, довольно изменчиво.

0 голосов
/ 15 апреля 2010

Может быть, вы предпочитаете /dev/urandom/ над /dev/random. Последний блокируется в Linux, если энтропии недостаточно, что может легко произойти, если программа работает на компьютере без взаимодействия с пользователем. В случае, если вы не можете открыть /dev/urandom, вы можете вызвать исключение вместо использования запасного варианта.

0 голосов
/ 15 апреля 2010

Определите хорошее. : -)

Важно ли быстро найти семя, или чтобы оно было как можно более случайным, независимо от того, сколько времени потребуется, чтобы собрать?

Для баланса - определенно не самый случайный, определенно не самый быстрый ...

  • При первом вызове укажите системное время в миллисекундах.
  • Запустите это через хеш-функцию, например, SHA-1.
  • Используйте результат в качестве начального числа.

Это должно дать вам в основном случайные 160 битов, что составляет 10 ^ 50 или около того изменчивости. Для запуска хеша потребуется доля секунды, так что это не молниеносно, но для меня это был хороший баланс в прошлом.

...