Генератор случайных чисел с энтропией

311
28 апреля 2017, 20:30

Необходимо сгенерировать случайные числа в диапазоне от 0 до 100 с шагом 1 (или 0..1 с шагом 0.01), причем с нормированной разницей/погрешностью (отклонение от равномерного распределения) не более 0,1 (т.е. разброс количества повторов не более 10% между минимальным и максимальным количеством) при достаточно небольшом общем количестве (скажем, всего 20000 случайных чисел).

Через rand(), соответственно, не выйдет, думаю насчет использования энтропии, random_device, увы, не подходит, т.к. и под Windows должно работать. Использую C++11, gcc 4.8, Qt 4.8, MinGW32.

При использовании функции CryptGenRandom нормированная разница около 0,6.

Answer 1

Все современные ГСЧ имеют равномерное распределение, других не бывает (точнее, их быстро исправляют, отклонение от равномерного распределения - это серьезный баг).

Когда вы N раз равномерно выбираете одно из M значений - число выборов каждого значения подчиняется биноминальному распределению с параметрами N, 1/M.

Интересующее вас значение, которое вы называете погрешностью, можно грубо оценить как отношение среднеквадратического отклонения к матожиданию (эта оценка очень не точная, но она использует довольно простые формулы и дает представление о порядке искомой величины).

Математическое ожидание для такого распределения равно N/M, а cреднеквадратическое отклонение этого распределения равно квадратному корню из N/M*(1 - 1/M). Отношение среднеквадратического отклонения к матожиданию равно квадратному корню из M/N*(1 - 1/M) = (M-1)/N. При M=100 и N=20000 это будет примерно 0.07, что довольно похоже на ваши результаты для CryptGenRandom.

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

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

Альтернативный вариант - считать сколько каких чисел было сгенерировано и после генерации каждого числа на основе этих данных пересчитывать распределение вероятностей для следующего числа.

Тут вам поможет алгоритм генерации случайного числа с табличным распределением.

READ ALSO
Thread или таймер

Thread или таймер

Каждые 6 секунд получаю данные с АЦП через COMPORTКак по-вашему лучше (правильнее) оформить: через поток или через компонент Timer прямо в основной...

237
Как сохранить бинарные данные в json?

Как сохранить бинарные данные в json?

Здравствуйте! Возник такой вопрос: как сохранить бинарный файл (png) в памяти в поле Json::value (библиотека jsoncpp)? Мне это нужно для того, чтоб потом...

263
Как написать код?

Как написать код?

Есть число n, а также массив, в котором дано m чисел

200