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 56

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):

  1. число различных случайных чисел, которые могут быть получены слишком малые: 32768. Если вам нужно больше различных случайных чисел, вам нужен другой способ (пример кода приведен ниже)
  2. сгенерированные числа слишком крупнозернистые: вы можете получить 1/32768, 2/32768, 3/32768, но никогда ничего между ними.
  3. ограниченные состояния генератора случайных чисел: после генерации случайных чисел 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 переполнения.

мое предположение заключается в том, что RAND_MAX равна INT_MAX и поэтому вы переполняете его до негатива.

просто сделать это:

r = ((double) rand() / (RAND_MAX)) + 1;

или даже лучше, используйте генераторы случайных чисел C++11.

это правильно:

double randd() {
  return (double)rand() / ((double)RAND_MAX + 1);
}

или

double randd() {
  return (double)rand() / (RAND_MAX + 1.0);
}