Функция rand()
возвращает псевдослучайное число от 0 до 2^31 -1. Она никогда не возвращает отрицательные числа, но при этом "ворует" аж половину диапазона возможных значений, ведь могла бы отдавать uint32_t, а не положительную половину int32_t. Как это исправить? И как запросить просто несколько псевдослучайных байт, но не "урезанных" на половину?
Меня интересуют именно библиотеки, которые можно было бы подключить через include и не переписывать код отдельно под windows/linux.
Следующий код показывает, что при использовании знаковых переменных первый бит "урезается". Почему так?
std::random_device RD;
std::uniform_int_distribution<int64_t> id;
std::uniform_int_distribution<uint64_t> uid;
std::cout << id.min() << std::endl;
std::cout << id.max() << std::endl;
std::cout << uid.min() << std::endl;
std::cout << uid.max() << std::endl;
Выхлоп:
0
9223372036854775807
0
18446744073709551615
Функция rand()
возвращает псевдослучайное число в диапазоне от 0
до RAND_MAX
. Чему равно RAND_MAX
- зависит от реализации. Из того, что в используемой вами реализации это значение равно 231-1 совсем не значит, что везде так.
Другими словами функция rand()
генерирует [log2(RAND_MAX+1)] псевдослучайных битов. Вызвав эту функцию несколько раз, вы можете получить сколько угодно псевдослучайных битов и "состыковать" эти биты в число любой разрядности.
Например, на вашей платформе
uint32_t r = ((uint32_t) RAND_MAX + 1) * rand() + rand();
даст вам псевдослучайное число в диапазоне uint32_t
.
Это, однако, несколько расточительно, ибо мы используем не все сгенерированные псевдослучайные биты. Не составит труда написать более общий вариант, который будет использовать rand()
для генерации непрерывного потока псевдослучайных битов, и затем "выкусывать" из него кусочки требуемой длины - хоть байтов, хоть килобайтов.
В любом случае, если вас в рамках вашей задачи удовлетворяют характеристики псевдослучайных чисел, генерируемых простейшими генераторами, то реализация функции типа rand()
занимает одну-две строчки. Реализуйте себе свою, под требуемый вам диапазон.
Функция rand() возвращает псевдослучайное число по РАВНОМЕРНОМУ закону распределения случайных чисел. Равномерное распределение чем характеризуется? Тем, что в среднем, по закону больших чисел, эти числа буду стремится к определенному "среднему" значению. rand() - всего лишь реализация закона распределения (и то, всего лишь псевдослучайная реализация). А не могли бы вы уточнить вопрос. Потому что спрашиваете про rand(), но почему-то функцию эту в коде не используете. Вместо этого пользуетесь классом uniform_int_distribution. При этому почему-то не пользуетесь возможностью этого класса: задавать минимальное и максимальное значения возможных случайных(!) чисел. Например
std::random_device rd; /*используется для получения начального числа для генератора случайных чисел*/
std::mt19937 gen(rd()); //стандартный mersenne_twister_engine с начальным числом rd()
std::uniform_int_distribution<> dis(1, 6); /*тут мы устанавливаем минимальное и максимально возможные числа, т.е. диапазон случайных чисел*/
for (int n=0; n<10; ++n)
/* можно использовать dis для преобразования случайного unsigned int, сгенерированного с помощью gen в int в диапазоне [1, 6] */
std::cout << dis(gen) << ' ';
Собственно в предыдущем ответе практически тоже самое, но в виде функции.
"Поэтому я не могу понять, почему для знаковых чисел min() установлен в 0, а не в минимальное значение типа данных." - потому что это реализация равномерного закона распределения. Посмотрите стандарный график такого закона распределения - и вам все сразу же станет ясно.
Еще пример
#include <iostream>
#include <random>
#include <ctime>
#include <string>
int main()
{
std::mt19937 gen(time(0));
std::uniform_int_distribution<int> uid1(0, 50), uid2(uid1.param());
std::cout << "uid1 max: " << uid1.max() << std::endl
<< "uid1 min: " << uid1.min() << std::endl
<< "uid2 max: " << uid2.max() << std::endl
<< "uid2 min: " << uid2.min() << std::endl;
}
На экране появится:
uid1 max: 50
uid1 min: 0
uid2 max: 50
uid2 min: 0
Можете попробовать этот код, только с указанием нужных Вам типов.
Похоже, что это должно решить Вашу проблему:
double random(double from, double to)
{
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<>urd(from, to);
return urd(mt);
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Мне нужно переместить list в set, я думал что для этого можно использовать функцию copy, но все оказалось не так просто, так как у класса set нету метода...
Есть два потока, когда начинается ввод в одном требуется остановить другой поток, как понять что ввод в первом потоке началсяЕсли использовать:
Необходимо продублировать все числа в строке, помогите исправить баг с бесконечным добавлением первого найденного числа