某个范围内的随机数c ++ [重复]
Posted
技术标签:
【中文标题】某个范围内的随机数c ++ [重复]【英文标题】:Random number c++ in some range [duplicate] 【发布时间】:2011-11-25 11:36:29 【问题描述】:可能重复:Generate Random numbers uniformly over entire range
我想在 C++ 中生成某个范围内的随机数,比如说我想要 25 到 63 之间的数字。
我怎样才能拥有它?
【问题讨论】:
即使有循环也能完美运行:输出 = min + (rand() % (int)(max - min + 1)) 【参考方案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()
返回从0
到RAND_MAX
(包含)的均匀分布的整数。现在,假设您通过使用std::rand() % RAND_MAX
获得了从0
到RAND_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 对我来说还可以(并且不时供快速参考),但我不会将其用作权威来源。
感谢您的信息。看了上面的资料,觉得自己有了更好的理解。我会争辩说,虽然我的答案不是最好的答案,但它没有用处。但这是你的决定,我再次感谢你启发我。 :)
见:azillionmonkeys.com/qed/random.html【参考方案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<>
包含在内——在上面的示例中,[25,63]
。
@Akiva 和 @polkovnikov.ph:这不是关于升级编译器(GCC 已经支持 C++11 很长时间了),而是关于使用 -std=c++11
编译器标志切换到 C++11 .由于 C++11 不向后兼容,所有符合标准的编译器(GCC、clang、...)都需要显式激活 C++11。以上是关于某个范围内的随机数c ++ [重复]的主要内容,如果未能解决你的问题,请参考以下文章