Разработка датчика случайных чисел, распределенных по требуемому закону

d180d0b0d0b7d180d0b0d0b1d0bed182d0bad0b0 d0b4d0b0d182d187d0b8d0bad0b0 d181d0bbd183d187d0b0d0b9d0bdd18bd185 d187d0b8d181d0b5d0bb d180 статьи

Нередко в своих программах нам приходится использовать генератор псевдослучайных чисел, или, как его еще называют, Random. С его помощью мы можем получать псевдослучайные числа, распределенные по равномерному закону. Иными словами, вероятности появления всех чисел одинаковы. Однако не всегда это удобно, и порой датчик, который мог бы генерировать числа как-то иначе, просто необходим, так что сейчас мы будем разбираться, как реализовать подобную штуку.

План действий

Первым делом нам нужно выбрать функцию плотности вероятности. Эта функция должна удовлетворять двум условиям:

  1. На заданном нами отрезке [a; b] функция должна быть положительной.
  2. Площадь под функцией на этом отрезке должна равняться единице.

В общем, все просто. Берем любую функцию, строим ее график и выбираем отрезок, на котором функция принимает положительные значения. Но тут может возникнуть проблема: площадь под выбранной функцией не равна единице. Чтобы это исправить, воспользуемся тем, что интересующая нас площадь ? есть площадь криволинейной трапеции, а она, в свою очередь, находится по формуле: Таким образом, найдя значение интеграла и разделив на него нашу функцию, мы получим новую функцию fk, которая будет удовлетворять всем нашим условиям. Теперь для получения одной случайной величины, нужно всего-навсего найти корень следующего уравнения, который и будет являться искомой величиной:

#image.jpgЗдесь V — случайная величина, равномерно распределенная на отрезке [0; 1], то есть величина, получаемая с помощью стандартного генератора псевдослучайных чисел.

Программная реализация

Создаем класс MyRandom, который будет наследоваться от стандартного класса Random.

Здесь func — функция, возвращающее значение левой части уже упомянутого выше уравнения:#image.jpg

Теперь осталось за малым, а именно переопределить все методы родительского класса.

На этом все. Единственное, на что следует обратить внимание, так это на следующее примечание с сайта msdn.microsoft.com:

Примечания для наследующих объектов

Начиная с платформы .NET Framework версии 2.0, при создании класса, производного от класса Random, и переопределении метода Sample распределение, предоставленное реализацией метода Sample в производном классе, не используется для вызова реализации следующих методов в базовом классе:

  • Метод Random.NextBytes(Byte[]).
  • Метод Random.Next().
  • Метод Random.Next(Int32, Int32), если (maxValue. — minValue) больше Int32.MaxValue.

Вместо них используется равномерное распределение, предоставляемое базовым классом Random. Такой принцип действия повышает общую производительность класса Random. Чтобы изменить данный принцип для вызова реализации метода Sample в производном классе, необходимо также переопределить принцип действия этих трех членов.

Оцените статью
Секреты программирования
Добавить комментарий