rand () между 0 и 1
таким образом, следующий код делает 0
r = ((double) rand() / (RAND_MAX))
почему имея r = ((double) rand() / (RAND_MAX + 1))
сделать -1
не должно ли добавление одного к RAND_MAX сделать 1
Edit: я получал предупреждение: переполнение целого числа в выражении
на этой линии, так что может быть проблема. Я только что сделал cout << r << endl
и это определенно дает мне значения между -1 и 0
6 ответов:
это конкретной реализации, но похоже, что в среде C++ вы работаете,
RAND_MAX
равнаINT_MAX
.из-за этого,
RAND_MAX + 1
проявляет неопределенное поведение (переполнение) и становится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
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)
.
нет, потому что RAND_MAX обычно расширяется до MAX_INT. Поэтому добавление одного (по-видимому) помещает его в MIN_INT (хотя это должно быть неопределенное поведение, как мне сказали), следовательно, разворот знака.
чтобы получить то, что вы хотите, вам нужно, чтобы переместить +1 вне расчета:
r = ((double) rand() / (RAND_MAX)) + 1;
Это не так. Это делает
0 <= r < 1
, но ваш оригинал0 <= r <= 1
.обратите внимание, что это может привести к неопределенное поведение если
RAND_MAX + 1
переполнения.