Сделать генератор случайных чисел со средним значением - PullRequest
0 голосов
/ 16 октября 2018

Мне нужно сделать генератор случайных чисел без встроенной функции и со средним значением не более 0,5.Он должен генерировать 10000 номеров, и желательно, чтобы они не повторялись.Например, код PRNG ниже:

#include <iostream>
using namespace std;

unsigned int Rand()
{
    static unsigned int seed = 5323;
    seed = 8253729 * seed + 2396403;
    return seed  % 32768;
}

int main()
{
    for (int count=1; count <= 10000; ++count)
{
        cout << Rand() << "\t";
        if (count % 10 == 0)
        cout << "\n";
}

    return 0;
}

В результате у меня есть 10000 чисел, и если я попытаюсь вычислить среднее значение из 10 чисел из первой строки, я не получу 0,5.Например, в первой строке мы получаем:

31222,24489,32444,25391,6402,11317,10440,6843,3598,3777

Среднее значение: 15592,3.Что я могу сделать с ним, чтобы уменьшить это значение?

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Rand() / 32767.0 будет иметь среднее значение 0,5.

Вам нужны знания по математике, статистике.Поиск ожидания, равномерное распределение.

0 голосов
/ 16 октября 2018

Не пытайтесь бросить свой собственный PRNG

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

Использование библиотеки <random>

C ++ имеет библиотечные функции, которые призваны сделать такую ​​проблему такой же безболезненной, какможно решить.

#include<random>
#include<iostream>

float get_random_value() {
    static std::default_random_engine engine{std::random_device()()};
    static std::uniform_real_distribution<float> distribution{0, 1};

    return distribution(engine);
}

int main() {
    for (int count=1; count <= 10000; ++count) {
        std::cout << get_random_value() << "\t";
        if (count % 10 == 0)
            std::cout << "\n";
    }
}

Компоненты этого кода выглядят так:

  • std::default_random_engine - это псевдоним для любого PRNG, который, по мнению вашей реализации библиотеки, идеально подходит для использования по умолчанию.Обычно по умолчанию это std::mt19937, который представляет собой тип PRNG, называемый «Twister Mersenne».Справочник <random> содержит множество других механизмов, которые вы могли бы вместо этого рассмотреть.
  • std::random_device - это библиотечная функция для запроса "энтропии" из операционной системы.Все, о чем вам нужно беспокоиться, это то, что он создается один раз, вызывается для генерации «семени», а затем отбрасывается и больше не используется.Если вы не используете это или если вы жестко кодируете значение, возвращаемое этим вызовом, движок всегда будет выдавать одни и те же значения в одном и том же порядке каждый раз, когда запускается ваша программа.
  • std::uniform_real_distribution - это распределение,Используя параметры, указанные для этого распределения, вы можете напрямую указать диапазон распространения.Мы использовали 0 и 1, поэтому распределение будет возвращать равномерно распределенные числа от 0 до 1. Доступны другие распределения, которые вы можете найти, описанные в справочнике.
  • Получить значение так же просто, каквызывая оператор вызова для объекта распределения, используя механизм в качестве единственного параметра.

Этот код будет надежно генерировать числа в диапазоне [0, 1), и это происходит в идиоматическом, выразительномманера.Если вам нужны одинаковые значения в другом диапазоне, этот код легко настроить для его обработки.Если вам нужны неоднородные значения (например, для нормального распределения), есть другие распределения (например, std::normal_distribution), которые правильно обрабатывают эту ситуацию.

...