C++ rand() 介于 0 和 1 之间

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9878965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:22:01  来源:igfitidea点击:

rand() between 0 and 1

c++random

提问by CyberShot

So the following code makes 0 < r < 1

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

r = ((double) rand() / (RAND_MAX))

Why does having r = ((double) rand() / (RAND_MAX + 1))make -1 < r < 0?

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

Shouldn't adding one to RAND_MAX make 1 < r < 2?

不应该在 RAND_MAX 上加 1 使 1 < r < 2?

Edit: I was getting a warning: integer overflow in expression

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

on that line, so that might be the problem. I just did cout << r << endland it definitely gives me values between -1 and 0

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

回答by Sam DeHaan

This is entirely implementation specific, but it appears that in the C++ environment you're working in, RAND_MAXis equal to INT_MAX.

这完全是特定实现的,但在您工作的 C++ 环境中,它似乎RAND_MAX等于INT_MAX.

Because of this, RAND_MAX + 1exhibits undefined (overflow) behavior, and becomes INT_MIN. While your initial statement was dividing (random # between 0 and INT_MAX)/(INT_MAX) and generating a value 0 <= r < 1, now it's dividing (random # between 0 and INT_MAX)/(INT_MIN), generating a value -1 < r <= 0

因此,RAND_MAX + 1表现出未定义(溢出)行为,并变为INT_MIN. 虽然您最初的语句是除法 (random # between 0 and INT_MAX)/( INT_MAX) 并生成一个 value 0 <= r < 1,但现在它正在除法 (random # between 0 and INT_MAX)/( INT_MIN),生成一个值-1 < r <= 0

In order to generate a random number 1 <= r < 2, you would want

为了生成随机数1 <= r < 2,您需要

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

回答by Serge Rogatch

rand() / double(RAND_MAX)generates a floating-point random number between 0 (inclusive) and 1 (inclusive), but it's not a good way for the following reasons (because RAND_MAX is usually 32767):

rand() / double(RAND_MAX)生成一个介于 0(含)和 1()之间的浮点随机数,但由于以下原因,这不是一个好方法(因为 RAND_MAX 通常为 32767):

  1. The number of different random numbers that can be generated is too small: 32768. If you need more different random numbers, you need a different way (a code example is given below)
  2. The generated numbers are too coarse-grained: you can get 1/32768, 2/32768, 3/32768, but never anything in between.
  3. Limited states of random number generator engine: after generating RAND_MAX random numbers, implementations usually start to repeat the same sequence of random numbers.
  1. 可以生成的不同随机数的个数太少:32768。如果需要更多不同的随机数,则需要不同的方式(下面给出了一个代码示例)
  2. 生成的数字过于粗粒度:您可以得到 1/32768、2/32768、3/32768,但不能介于两者之间。
  3. 随机数生成器引擎的限制状态:生成 RAND_MAX 个随机数后,实现通常开始重复相同的随机数序列。

Due to the above limitations of rand(), a better choice for generation of random numbers between 0 (inclusive) and 1 (exclusive) would be the following snippet (similar to the example at http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution):

由于 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;
}

This is easy to modify to generate random numbers between 1 (inclusive) and 2 (exclusive) by replacing unif(0, 1)with unif(1, 2).

这是很容易通过更换修改到1之间(含)和2(不包括)产生的随机数unif(0, 1)unif(1, 2)

回答by Tudor

No, because RAND_MAX is typically expanded to MAX_INT. So adding one (apparently) puts it at MIN_INT (although it should be undefined behavior as I'm told), hence the reversal of sign.

不,因为 RAND_MAX 通常扩展为 MAX_INT。因此,添加一个(显然)将其置于 MIN_INT (尽管正如我所说,它应该是未定义的行为),因此符号的反转。

To get what you want you will need to move the +1 outside the computation:

为了得到你想要的东西,你需要将 +1 移到计算之外:

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

回答by Luchian Grigore

It doesn't. It makes 0 <= r < 1, but your original is 0 <= r <= 1.

它没有。它使0 <= r < 1,但你原来是0 <= r <= 1

Note that this can lead to undefined behaviorif RAND_MAX + 1overflows.

请注意,如果溢出,这可能会导致未定义的行为RAND_MAX + 1

回答by Pubby

My guess is that RAND_MAXis equal to INT_MAXand so you're overflowing it to a negative.

我的猜测是它RAND_MAX等于INT_MAX,所以你将它溢出到负数。

Just do this:

只需这样做:

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

Or even better, use C++11's random number generators.

或者更好的是,使用 C++11 的随机数生成器。

回答by KIM Taegyoon

This is the right way:

这是正确的方法:

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

or

或者

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

回答by SeveneduS

In my case (I'm using VS 2017) works fine the following simple code:

在我的情况下(我使用的是 VS 2017)下面的简单代码可以正常工作:

#include "pch.h"
#include <iostream>
#include <stdlib.h>
#include <time.h>

int main()
{
    srand(time(NULL));

    for (int i = 1000; i > 0; i--) //try it thousand times
    {
        int randnum = (double)rand() / ((double)RAND_MAX + 1);
        std::cout << " rnum: " << rand()%2 ;
    }
}