Как сделать генератор случайных чисел в C++

Я читал одну книгу по C++ и дошел до темы с генератором случайных чисел Но не совсем понимаю как он работает. В книге сказано что компьютер генерирует псевдослучайные числа т.е. числа не являющиеся абсолютно случайными, и как будто есть решение. Насколько я понял 9 строка делает посев генератора случайных чисел и привязывается ко времени в системе. В книге оно выглядит вот так:

введите сюда описание изображения

Но генерируются очень близкие по значению числа:

введите сюда описание изображения

Мне хотелось бы написать абсолютный генератор случайных чисел без привязки к времени. Пробовал убрать 9 строку но программа всегда выводит 41.


Ответы (3 шт):

Автор решения: Serge3leo

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

Абсолютных ГСЧ не бывает, к примеру, смотрите обсуждение у Кнута, Искусство программирования, т2.

Без привязки ко времени, то как минимум, при инициализации:

  1. Использовать инструкцию процессора RDRAND, под VS: _rdrand16_step() и _rdrand32_step() (правда, это зависит от платформы);
  2. Использовать общесистемный генератор случайных чисел, под Windows: CryptGenRandom() How to get "cryptographically strong" random bytes with Windows APIs?
  3. Использовать С++11 class std::random_device, однако, стандарт не даёт никаких гарантий, поэтому на каждой платформе с каждой новой версией придётся проверять, что требует существенной квалификации. https://en.cppreference.com/w/cpp/numeric/random/random_device
→ Ссылка
Автор решения: DmitriySidyakin

Вот мой пример исходного кода моей простой функции генерации случайных чисел:

#include <iostream>

using namespace std;

int _a = 23456781;
int _b = 12323456781;
int _mod = 56472311456;
int _seed = 5123;

long rnd()
{
    _seed = (_a * _seed + _b) % _mod;
    _mod = _mod / 0.5;
    return _seed;
}

int main() {
    for (int i = 0; i < 10; i++) {
        int random = rnd();
        cout << random << endl;
    }

    return 0;
}

Это генерация чисел на основе переполнения разрядной сетки.

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

Вот вторая функция для генерации случайного числа, сравните с её распределением:

long _x = 123; // начальные значения могут быть другими
long _y = 456;
long _z = 789;
long _w = 768;
long _seed2 = (long)_w;

long rnd2()
{
    long t = _x ^ (_x << 11);
    _x = _y;
    _y = _z;
    _z = _w;
    _w = (_w ^ (_w >> 19)) ^ (t ^ (t >> 8));
    _seed2 = (long)_w;
    return _seed2;
}

Вот пример первой последовательности rnd:

-13703724
-596357103
-235551766
-302927377
-433953744
-107717251
-1332608410
-932762053
-1565801460
-558298199

Вот rnd2:

252067
890666
1385621
868244
517290486
1913473473
613808793
1292734464
94374622
502991082
→ Ссылка
Автор решения: Dimazda 04

Во первых, приношу извинения за неправильно сформулированный вопрос, во вторых я наивно полагал что ГСЧ в С++ работает как и в Python, но кое-что не учёл и теперь сижу ломаю голову.
В Python есть функция:

num = random.randint(a, b)

принимающая на вход два значения, a и b - диапазон чисел, из которого будут отбираться числа.
В С++ это выглядит иначе. Я немного покопался, и написал это:

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

using namespace std;

int main ()
{
    srand(time(0));
    int a = 10;
    int b = 1;
    

    for (int i = 0; i < 10; ++i) {
        int random = rand();
        random = (random % a) + b;
        cout << random << endl;
    }
    
    return 0;
}

По сути это то же самое, что и randint() в Python, число b - это начало диапазона, a - это количество чисел для выборки, как в примере начало диапазона 1, количество чисел 10.

→ Ссылка