2

所以,我一直对此很着迷。

rand() % 6 将始终产生 0-5 之间的结果。

但是,当我需要介于两者之间时,比如说 6-12。

我应该有 rand() % 6 + 6

0+6 = 6.
1+6 = 7.
...
5+6 = 11. ???

如果我想要 6-12 的区间,我需要 + 7 吗?但是,0+7 = 7。什么时候会随机化 6?

我在这里想念什么?哪一种是在 6 到 12 之间获得随机数的正确方法?为什么?好像我在这里遗漏了一些东西。

4

4 回答 4

12

如果C++11是一个选项,那么您应该使用随机标头uniform_int_distrubution正如詹姆斯在使用rand的评论中指出的那样,存在%很多问题,包括有偏差的分布:

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;

    std::mt19937 e2(rd());

    std::uniform_int_distribution<int> dist(6, 12);

    for (int n = 0; n < 10; ++n) {
            std::cout << dist(e2) << ", " ;
    }
    std::cout << std::endl ;
}

如果你必须使用rand那么应该这样做:

rand() % 7 + 6

更新

更好的使用方法rand如下:

6 + rand() / (RAND_MAX / (12 - 6 + 1) + 1)

我从C 常见问题解答中获得了这个,并解释了如何获得一定范围内的随机整数?问题。

更新 2

Boost也是一种选择:

#include <iostream>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

int main()
{
  boost::random::mt19937 gen;
  boost::random::uniform_int_distribution<> dist(6, 12);

  for (int n = 0; n < 10; ++n) {
    std::cout << dist(gen) << ", ";
  }
  std::cout << std::endl ;
}
于 2013-10-23T22:15:45.597 回答
5

你需要 rand() % 7 + 6。

rand() %7 中的最小数字:0。 rand() %7 中的最大数字:6。

0 + 6 = 6。6 + 6 = 12。

于 2013-10-23T22:14:35.947 回答
4

模运算a % b计算除法的余数a / b。显然,除法的余数必须小于b,如果a是一个随机正整数,那么a%b它是一个在 0 .. (b-1) 范围内的随机整数


在您提到的评论中:

rand()%(最大-最小)+最小

该算法产生半开范围 [min, max) 中的值。(也就是说,max 在范围之外,只是表示边界。由于我们讨论的是整数范围,所以这个范围相当于封闭范围 [min, max-1]。)

当您写“0 - 5”或“6 - 12”时,这些是封闭范围。要使用上述等式,您必须使用表示等效半开范围的值:[0, 6) 或 [6, 13)。

rand() % (6-0) + 0

rand() % (13-6) + 6

请注意,这rand() % (max-min) + min只是您显然已经了解的规则的概括:rand() % n产生范围为 0 - (n-1) 的值。等效的半开范围是 [0, n) 和rand() % n== rand() % (n-0) + 0

所以教训是:不要将半开范围与封闭范围混淆。


第二个教训是,这显示了另一种比手动计算自己的分布<random>更容易使用的方法。rand()内置uniform_int_distribution允许您直接说明所需的包含范围。如果你想要范围 0-5 你说uniform_int_distibution<>(0, 5),如果你想要范围 6-12 那么你说uniform_int_distribution<>(6, 12)

#include <random>
#include <iostream>

int main() {
  std::default_random_engine eng;
  std::uniform_int_distribution<> dist(6, 12);

  for (int i=0; i<10; ++i)
    std::cout << dist(eng) << " ";
}

rand()%7+6更简洁,但这并不意味着它更容易使用。

于 2013-10-24T16:44:24.430 回答
1

这里有几个概念。

首先,有范围:[表示包括在内。)表示排他性。

模运算符 % n 产生[0,n)- 0,..n-1

当您向该结果添加一个值时,您将向范围的两端添加相同的值:

%n + 6 = [n,n+6)

现在,如果 n 是 6,就像你的情况一样,你的输出将是[0,6)

%6 + 6 = [6,12)

现在你想要的是[6,13)

从中减去 6:

[0,7) + 6 => n%7 + 6

其次,还有使用 rand() 的问题。这取决于您是否真的关心您的数据是否是随机的。如果你真的很在意它是随机的,我强烈建议在今年的 Going Native 2013上观看 Stefan T Lavalej 关于使用 rand() 的陷阱的演讲。他还谈到了你应该使用什么。

如果 rand() 的随机性对你来说并不重要,那么一定要使用它。

于 2013-10-23T23:03:21.853 回答