Rand() между 0 и 1
Таким образом, следующий код делает 0 < r < 1
r = ((double) rand() / (RAND_MAX))
Почему создание r = ((double) rand() / (RAND_MAX + 1))
делает -1 < r < 0?
Не следует добавлять одно к RAND_MAX, чтобы сделать 1 < r < 2?
Изменить: я получал предупреждение: целочисленное переполнение в выражении
на этой строке, так что это может быть проблемой. Я просто сделал cout << r << endl
, и он определенно дает мне значения между -1 и 0
Ответы
Ответ 1
Это полностью специфичный для реализации, но похоже, что в среде С++, в которой вы работаете, RAND_MAX
равно INT_MAX
.
Из-за этого RAND_MAX + 1
демонстрирует поведение undefined (переполнение) и становится INT_MIN
. В то время как ваш начальный оператор делялся (случайным образом # между 0 и INT_MAX
)/(INT_MAX
) и генерировал значение 0 <= r < 1
, теперь он делит (случайный # между 0 и INT_MAX
)/(INT_MIN
), генерируя значение -1 < r <= 0
Чтобы создать случайное число 1 <= r < 2
, вам нужно
r = ((double) rand() / (RAND_MAX)) + 1
Ответ 2
Нет, поскольку RAND_MAX обычно расширяется до MAX_INT. Поэтому добавление одного (по-видимому) помещает его в MIN_INT (хотя это должно быть поведение undefined, как я сказал), следовательно, обращение знака.
Чтобы получить то, что вы хотите, вам нужно будет переместить +1 за пределы вычислений:
r = ((double) rand() / (RAND_MAX)) + 1;
Ответ 3
rand() / double(RAND_MAX)
генерирует случайное число с плавающей запятой между 0 (включительно) и 1 (включительно), но это не очень хорошо по следующим причинам (поскольку RAND_MAX обычно 32767):
- Количество различных случайных чисел, которые могут быть сгенерированы, слишком мало: 32768. Если вам нужны более разные случайные числа, вам нужен другой способ (пример кода приведен ниже)
- Сгенерированные числа слишком грубые: вы можете получить 1/32768, 2/32768, 3/32768, но никогда ничего между ними не было.
- Ограниченные состояния двигателя генератора случайных чисел: после генерации случайных чисел RAND_MAX реализации обычно начинают повторять одну и ту же последовательность случайных чисел.
Из-за вышеуказанных ограничений rand() лучший выбор для генерации случайных чисел между 0 (включительно) и 1 (эксклюзивный) был бы следующим фрагментом (похожим на пример в http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution):
#include <iostream>
#include <random>
#include <chrono>
int main()
{
std::mt19937_64 rng;
// initialize the random number generator with time-dependent seed
uint64_t timeSeed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::seed_seq ss{uint32_t(timeSeed & 0xffffffff), uint32_t(timeSeed>>32)};
rng.seed(ss);
// initialize a uniform distribution between 0 and 1
std::uniform_real_distribution<double> unif(0, 1);
// ready to generate random numbers
const int nSimulations = 10;
for (int i = 0; i < nSimulations; i++)
{
double currentRandomNumber = unif(rng);
std::cout << currentRandomNumber << std::endl;
}
return 0;
}
Это легко изменить для генерации случайных чисел между 1 (включительно) и 2 (эксклюзивным), заменив unif(0, 1)
на unif(1, 2)
.
Ответ 4
Это не так. Он делает 0 <= r < 1
, но ваш оригинал 0 <= r <= 1
.
Обратите внимание, что это может привести к undefined поведению, если RAND_MAX + 1
переполняется.
Ответ 5
Я предполагаю, что RAND_MAX
равен INT_MAX
, и поэтому вы переполняете его на отрицательный.
Просто сделайте следующее:
r = ((double) rand() / (RAND_MAX)) + 1;
Или даже лучше, используйте генераторы случайных чисел С++ 11.
Ответ 6
Это правильный путь:
double randd() {
return (double)rand() / ((double)RAND_MAX + 1);
}
или
double randd() {
return (double)rand() / (RAND_MAX + 1.0);
}