Каким образом можно использовать генерацию случайных чисел в C++?

Какими методами можно генерировать случайные числа вместо использования функции rand()? Как исправить проблему с генерацией одинаковых чисел при быстрой работе процедуры? Требуется метод генерации случайных чисел для создания тестовых данных.
  • 2 февраля 2024 г. 9:00
Ответы на вопрос 3
В C++ для генерации случайных чисел стандартная библиотека предоставляет несколько механизмов, которые являются более предпочтительными, чем использование устаревшей функции `rand()`.

### Использование `<random>` (С++11 и позже)

Стандартная библиотека C++ включает в себя библиотеку `<random>`, которая предоставляет различные генераторы случайных чисел и распределения. Ниже приведен пример генерации случайных чисел с использованием этой библиотеки:

```cpp
#include <iostream>
#include <random>

int main() {
    // Инициализация генератора случайных чисел
    std::random_device rd;  // Устройство для получения случайного начального числа
    std::mt19937 gen(rd()); // Мерсенн вихрь (алгоритм генерации псевдослучайных чисел)

    // Равномерное распределение в диапазоне от 10 до 20
    std::uniform_int_distribution<> dis(10, 20);

    // Генерация случайных чисел
    for (int n = 0; n < 10; ++n) {
        std::cout << dis(gen) << ' ';
    }

    std::cout << '\n';
    return 0;
}
```

В этом примере `std::random_device` используется для получения начального числа, a `std::mt19937` – это генератор сборки на основе алгоритма Мерсенна. `std::uniform_int_distribution` представляет равномерное распределение целых чисел.

### Исправление проблемы с одной и той же последовательностью

Проблема с одинаковыми числами обычно возникает, если в качестве начального числа (seed) для генератора случайных чисел передаётся одно и то же значение. При использовании `rand()` решить эту проблему можно обновлением seed, например, с помощью вызова `srand(time(NULL))` перед генерацией чисел. Однако при частых вызовах в коротком промежутке времени `time(NULL)` может вернуть одно и то же значение, что приведёт к генерации одинаковой последовательности.

Улучшенные генераторы как в примере выше (`std::mt19937` с начальным числом от `std::random_device`) решают эту проблему за счёт получения более качественного начального числа. `std::random_device` должен генерировать непредсказуемое начальное число (seed), если хардварные источники энтропии на вашей системе в наличии.

### Генерация тестовых данных

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

Вот пример генерации случайных вещественных чисел в диапазоне от 0.0 до 1.0:

```cpp
// Равномерное распределение в диапазоне от 0.0 до 1.0
std::uniform_real_distribution<> dis(0.0, 1.0);

// Генерация случайных вещественных чисел
for (int n = 0; n < 10; ++n) {
    std::cout << dis(gen) << ' ';
}
```

А
srand вызывайте только один раз где-нибудь в начале программы. А потом сколько угодно раз используйте rand. 

srand устанавливает состояние генератора псевдослучайных чисел. В качестве seed вы там используете количество миллисекунд, которое целую миллисекунду одинаковое, поэтому состояние генератора у вас в каждой функции rand_offer одно и то же - поэтому числа и генерируются одни и теже. sleep(1) лечит проблему потому, что следующий вызов посчитает другое значение count_ms.
Числа одинаковые потому что srand устанавливает начальное число от которого и происходит вычисление каждого случайного числа. Поэтому вынесите srand из этой функции. И наверное лучше не использовать srand постоянно. Если хотите можете таймер сделать например каждые пять минут вызывать srand
Похожие вопросы