rand()介于0和1之间

Cyb*_*hot 68 c++ random

所以下面的代码使0 <r <1

r = ((double) rand() / (RAND_MAX))
Run Code Online (Sandbox Code Playgroud)

为什么 r = ((double) rand() / (RAND_MAX + 1))让-1 <r <0?

不应该向RAND_MAX添加一个使1 <r <2?

编辑:我收到一个警告:表达式中的整数溢出

在那条线上,这可能是问题所在.我刚刚做了cout << r << endl,它肯定给了我介于-1和0之间的值

Sam*_*aan 78

这完全是特定实现的,但似乎在您正在使用的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
Run Code Online (Sandbox Code Playgroud)

  • 为什么要在 `RAND_MAX` 两边加上括号? (2认同)

Ser*_*tch 24

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;
}
Run Code Online (Sandbox Code Playgroud)

通过替换unif(0, 1),可以很容易地修改以生成1(包括)和2(不包括)之间的随机数unif(1, 2).


Tud*_*dor 17

不,因为RAND_MAX通常会扩展为MAX_INT.所以添加一个(显然)将它放在MIN_INT(虽然它应该是我所说的未定义的行为),因此符号的反转.

要得到你想要的东西,你需要在计算之外移动+1:

r = ((double) rand() / (RAND_MAX)) + 1;
Run Code Online (Sandbox Code Playgroud)

  • 添加一个*可以*把它放在MIN_INT,但它仍然是UB. (2认同)
  • 添加一个导致未定义的行为,因为所有溢出.这是错误的和误导性的,因为它似乎有效.要么纠正你的答案,要么删除它. (2认同)