Это, казалось бы, распространенный вопрос, поэтому я надеюсь, что не прозвучу лишним. Но диапазон, возвращаемый из rand(), должен быть между 0 и RAND_MAX, однако, когда я делаю очень простой оператор rand, я всегда получаю возврат в очень небольшом диапазоне.
Этот диапазон примерно равен 1,4XX,XXX,XXX. Я подумал, что это могут быть часы, поэтому я подождал тридцать минут, и я все еще получаю числа в том же диапазоне.
Вот пример вывода двадцатиминутной давности:
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439810968
80
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439827775
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439827775
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439844582
78
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439878196
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1439895003
78
и вот пример вывода только что:
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456483512
78
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456500319
80
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456500319
80
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456517126
29
Matthews-Macbook-Pro:Data_Structures matthewwright$ ./main
1456533933
78
Я знаю, что rand() не идеален, но это кажется слишком похожим, чтобы быть правильным. Если диапазон равен 0 - RAND_MAX, кажется странным, что все возвращаемые числа находятся в одном и том же диапазоне.
Вот код, который я тестировал:
#include <iostream>
#include <stdio.h> /* printf, scanf, puts, NULL */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
int main(int argc, char const *argv[])
{
/* declarations */
srand(time(NULL));
std::cout << std::rand() << std::endl;
std::cout << std::rand()%100 << std::endl;
return 0;
}
Я не думаю, что мне нужны все эти операторы #include, но я видел, как их используют другие люди, поэтому я включил их на тот случай, если это повлияет на мой вывод, но это не так.
Редактировать
Поэтому ссылки, предоставленные @Mgetz и @Curious, оказались очень полезными. Чтобы консолидировать,
Информационная страница: http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
Очень полезная лекция (на самом деле, посмотрите это): https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
Я резюмировал то, что услышал на лекции, в своих заметках, просто чтобы мне не пришлось заново исследовать это в другой раз, если я забуду. Я не писал код здесь, большая часть кода находится на этой «Информационной странице», указанной выше. Большинство комментариев содержат информацию из лекции, хотя это не дословно из лекции. Еще раз, очень рекомендую посмотреть. Он насыщен хорошей информацией.
#include <iostream>
#include <random>
int main(int argc, char const *argv[])
{
/* https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful */
/* Randomness Verson 1 : Deterministic */
std::mt19937 mt(1234);
std::uniform_int_distribution<int> dist(0,127);
/* Default is int, but we could specify others.
* The range is [inclusive, inclusive]
*
* Above is Mersenne Twister RNG. It is deterministic, meaning we can get the same result
* if we use "std::mt19937 mt(1234)"; or something like that. This could be useful for some
* people (He mentions games, some experiments, et cetera). It is stupid fast.
*
* However, it isn't cryptographically secure, but it pretty random as random goes. If you
* track the output though, you could guess the next numbers, so don't use it for anything
* secure.
*/
/* Randomness Verson 2 */
std::random_device rd; //Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); //Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<int> dis(0, 127); // Inclusive
/* This is not reproducible. This is not deterministic.
* "Possibly Crypto-secure." Seems like using Random Device makes this near perfect random,
* assuming some conditions. I'm not a man who's written security software, and if you are
* writing security software, I assume you're not looking at StackOverflow to figure out how
* to do random numbers. The way he talked about it in the lecture made this seem much more
* secure, but I'm not sure what I'm talking about when it comes to these things
*/
for (int i = 0; i < 3; ++i)
{
/* Below would output the pure Mersenne Twister output, deterministic. This seems to
* be pretty random, but it isn't totally random. */
std::cout << dist(mt) << " ";
/* And below would output the random device output. This should be slower, but
* more truly random. */
//Use dis to transform the random unsigned int generated by gen into an int in [1, 6]
std::cout << dis(gen) << " ";
std::cout<< std::endl;
}
}
time(NULL)
имеет разрешение в 1 секунду, поэтому он будет предоставлять одно и то же начальное значение для каждого экземпляра вашей программы, который запускается в одну и ту же секунду. - person François Andrieux   schedule 12.07.2017srand
/rand
довольно плоха. Аналогичный вопрос: stackoverflow.com/questions/3032726/ - person Rakete1111   schedule 12.07.2017rand()
считается вредной - person Mgetz   schedule 12.07.2017std::cout<<time(NULL)<<std::endl;
- person Richard   schedule 13.07.2017auto ts=time(NULL);srand(ts);std::cout<<ts<<" "<<rand()<<std::endl;
- person Richard   schedule 13.07.2017time(NULL)
, не обязательно должно быть числом секунд (хотя обычно это так)? Одна из гипотез, которые у меня были относительно поведения, которое вы видели, заключалась в том, что вы получали возврат отtime(NULL)
с несколькими установленными младшими битами. Приведение этого кint
приведет к потере большей части вашего семени. - person Richard   schedule 13.07.2017clang++ --version
илиg++ --version
. - person Richard   schedule 13.07.2017