Как сделать генератор случайных чисел в C++
Я читал одну книгу по C++ и дошел до темы с генератором случайных чисел Но не совсем понимаю как он работает. В книге сказано что компьютер генерирует псевдослучайные числа т.е. числа не являющиеся абсолютно случайными, и как будто есть решение. Насколько я понял 9 строка делает посев генератора случайных чисел и привязывается ко времени в системе. В книге оно выглядит вот так:
Но генерируются очень близкие по значению числа:
Мне хотелось бы написать абсолютный генератор случайных чисел без привязки к времени. Пробовал убрать 9 строку но программа всегда выводит 41.
Ответы (3 шт):
Мне хотелось бы написать абсолютный генератор случайных чисел без привязки к времени.
Абсолютных ГСЧ не бывает, к примеру, смотрите обсуждение у Кнута, Искусство программирования, т2.
Без привязки ко времени, то как минимум, при инициализации:
- Использовать инструкцию процессора
RDRAND
, под VS:_rdrand16_step()
и_rdrand32_step()
(правда, это зависит от платформы); - Использовать общесистемный генератор случайных чисел, под Windows:
CryptGenRandom()
How to get "cryptographically strong" random bytes with Windows APIs? - Использовать С++11
class std::random_device
, однако, стандарт не даёт никаких гарантий, поэтому на каждой платформе с каждой новой версией придётся проверять, что требует существенной квалификации. https://en.cppreference.com/w/cpp/numeric/random/random_device
Вот мой пример исходного кода моей простой функции генерации случайных чисел:
#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
Во первых, приношу извинения за неправильно сформулированный вопрос, во вторых я наивно полагал что ГСЧ в С++ работает как и в 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
.