【问题标题】:Random number c++ in some range [duplicate]某个范围内的随机数c ++ [重复]
【发布时间】:2011-11-25 11:36:29
【问题描述】:

可能重复:
Generate Random numbers uniformly over entire range

我想在 C++ 中生成某个范围内的随机数,比如说我想要 25 到 63 之间的数字。

我怎样才能拥有它?

【问题讨论】:

  • 即使有循环也能完美运行:输出 = min + (rand() % (int)(max - min + 1))

标签: c++ random


【解决方案1】:
int range = max - min + 1;
int num = rand() % range + min;

【讨论】:

  • 不好的建议。这不会产生均匀分布。虽然这是一种相当普遍的方法(但存在根本缺陷)。
  • 为什么会有缺陷?如果rand() % range 相对统一,我希望添加一个常量可以保持统一。或者你是说rand() 本身并不是一个真正随机数的好选择?没错,但取决于 OP 想要做什么, rand() 可能就足够了。
  • @Anson:Johannes Rudolph 抱怨的原因是 % 不起作用,除非右边的值是 RAND_MAX 的精确除数。如果不是,那么某些值的概率会稍小(非常轻微)。示例: RAND_MAX (32767) r = rand()%3; 概率为 0(10923/32767) 1(10922/32767) 2(10922/32767) 请注意,0 的概率略高。正如 'Benjamin Lindley' 指出的那样,这在大多数情况下是微不足道的,但是当你做像密码学这样的事情时,这样的事情就会成为一个问题。所以很多人在使用这种方法时都会哭。
  • 还有一个问题是 rand() 的底部几位不是很随机(因此,如果 max-min 很小,您就不会得到好的值(这可能已经修复))。另一种选择是num = rand() * 1.0 / RAND_MAX * (max-min+1) + min;
  • @MartinYork 你的替代方案也好不到哪里去,它仍然存在鸽巢问题,只是原因不那么明显。
【解决方案2】:

您可以使用添加到标准库 (TR1) 中的随机功能。或者您可以使用在普通 C 中工作的相同旧技术:

25 + ( std::rand() % ( 63 - 25 + 1 ) )

【讨论】:

  • 请注意,这个答案不会产生同样可能的数字!下面的答案是更好的方法。
  • @GeorgeHilliard 为什么?我真的不知道,生成随机数的算法是如何工作的
  • @milanHrabos 一个例子可以很容易地说明这一点:std::rand() 返回从0RAND_MAX包含)的均匀分布的整数。现在,假设您通过使用std::rand() % RAND_MAX 获得了从0RAND_MAX - 1(包括)范围内的整数,现在获得0 的机会将加倍,因为这将是std::rand() 返回时的结果要么 0 要么 RAND_MAX。任何其他数字只有在std::rand() 直接返回时才会获得。这同样适用于不是 RAND_MAX + 1 的除数的每个模数。
  • @GeorgeHilliard "Below" 是相对的。
【解决方案3】:
float RandomFloat(float min, float max)
{
    float r = (float)rand() / (float)RAND_MAX;
    return min + r * (max - min);
}

【讨论】:

  • 这不是均匀分布。尝试将 7 个球放入 3 个桶中,使每个桶中的球数量相同。你做的完全一样。
  • 我实际上认为它是正确的,它将一个范围乘以 [0,1] 中的一个数字。你能进一步解释@polkovnikov.ph 吗?
  • @LorenzoBelli 浮点数不是均匀分布在 [0, 1] 上的,因为它们的精度有限。实数是。
  • 告诉我,这个算法返回max的几率是多少?
【解决方案4】:

使用rand函数:

http://www.cplusplus.com/reference/clibrary/cstdlib/rand/

引用:

A typical way to generate pseudo-random numbers in a determined range using rand is to use the modulo of the returned value by the range span and add the initial value of the range:

( value % 100 ) is in the range 0 to 99
( value % 100 + 1 ) is in the range 1 to 100
( value % 30 + 1985 ) is in the range 1985 to 2014

【讨论】:

  • @Tux-D 这是从 cplusplus 网站直接复制的 sn-p 代码,所以我想我认为这是执行此操作的标准方式。我没有意识到这样做是不正确或不常见的,感谢您提供的信息。因为现在我很好奇,这个方法到底有什么问题?
  • 请参阅上面的Benjamin Lindley 答案和我的相关 cmets,了解 C++11 之前的方法。但是我上面的评论是错误的(我想念你的答案)。所以我会删除它。网站 cplusplus.com 对我来说还可以(并且不时供快速参考),但我不会将其用作权威来源。
  • 感谢您的信息。看了上面的资料,觉得自己有了更好的理解。我会争辩说,虽然我的答案不是最好的答案,但它没有用处。但这是你的决定,我再次感谢你启发我。 :)
【解决方案5】:
int random(int min, int max) //range : [min, max]
{
   static bool first = true;
   if (first) 
   {  
      srand( time(NULL) ); //seeding for the first time only!
      first = false;
   }
   return min + rand() % (( max + 1 ) - min);
}

【讨论】:

  • 希望您不要介意编辑,我很确定这是您的意图。
  • 要包含最大值,您必须使用 max - min + 1
  • 它是否包含从负到正的范围?
  • 使用“return min + rand() % (max + 1 - min);”获得最大值本身! =D
  • rand() 仅返回带 [0;RAND_MAX] 中的数字。如果 (max - min) > RAND_MAX,你永远不会得到范围内的数字 (RAND_MAX; max - min)。 RAND_MAX 是实现细节,但通常等于 7FFF。
【解决方案6】:

由于还没有人发布现代 C++ 方法,

#include <iostream>
#include <random>
int main()
{
    std::random_device rd; // obtain a random number from hardware
    std::mt19937 gen(rd()); // seed the generator
    std::uniform_int_distribution<> distr(25, 63); // define the range

    for(int n=0; n<40; ++n)
        std::cout << distr(gen) << ' '; // generate numbers
}

【讨论】:

  • 如果您想知道“mt19937 类型的黑客是什么?!” - A Mersenne Twister pseudo-random generator of 32-bit numbers with a state size of 19937 bits. 它是带有预设参数的“mersenne_twister_engine”模板 (cplusplus.com/reference/random/mersenne_twister_engine) 的“包装器”。
  • @Akiva 我认为,最后一个是正确的。如果您的发行版中没有它,您应该将您的编译器升级到符合 C++11 的编译器。它不是一个弃用的功能,它是一个新功能。 GCC 4.9+ 当然应该有它。
  • 另外值得注意的是,要对浮点数/双精度数做同样的事情,可以使用 std::uniform_real_distribution。很好的答案!
  • 请注意,std::uniform_int_distribution&lt;&gt; 包含在内——在上面的示例中,[25,63]
  • @Akiva 和 @polkovnikov.ph:这不是关于升级编译器(GCC 已经支持 C++11 很长时间了),而是关于使用 -std=c++11 编译器标志切换到 C++11 .由于 C++11 不向后兼容,所有符合标准的编译器(GCC、clang、...)都需要显式激活 C++11。
猜你喜欢
  • 2019-08-31
  • 1970-01-01
  • 2011-02-27
  • 2017-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多