随机数发生器,C++
一种常见的方法是使用std::rand()
与模:
#include<cstdlib>
#include<ctime>
// ...
std::srand(std::time(0)); // needed once per program run
int r = std::rand() % 14620 + 1;
然而,随着@tenfour在他的回答中提到,模运算符可以破坏值std::rand()
回报的均匀性。这是因为模数将它丢弃的值转换为有效值,并且这种转换可能不一致。例如,对于[0,10]中的n
,值n % 9
将9转换为0,因此您可以通过将真零或9转换为零来获得零。其他值只有一个机会产生。
另一种方法是将随机数从std::rand()
转换为[0,1]范围内的浮点值,然后转换并将值移动到您希望的范围内。
int r = static_cast<double>(std::rand())/RAND_MAX * 14620 + 1;
使用rand。
(rand() % 100) is in the range 0 to 99
(rand() % 100 + 1) is in the range 1 to 100
(rand() % 30 + 1985) is in the range 1985 to 2014
(rand() % 14620 + 1) is in the range 1 to 14620
编辑:
为链接提到的,随机使用前应进行使用srand
接种。使用一个共同的独特价值是致电time
的结果。
srand()/rand()
是你所需要的功能的教程,正如其他人回答。
%
的问题在于结果显然是不均匀的。为了说明,假设rand()
返回0-3的范围。以下是称这是4000倍的假设结果:
0 - 1000 times
1 - 1000 times
2 - 1000 times
3 - 1000 times
现在,如果你对(rand() % 3)
做同样的取样,你会发现结果会是这样:
0 - 2000 times
1 - 1000 times
2 - 1000 times
哎哟!更均匀的溶液是这样的:
int n = (int)(((((double)std::rand())/RAND_MAX) * 14620) + 1);
对不起,草率的代码,但这个想法是正确比例缩小到你想要使用浮点运算的范围内,并转换为整数。
如果你有一个C++ 0x中的环境,升压11b的接近衍生物为现在的标准:
#include <random>
#include <iostream>
int main()
{
std::uniform_int_distribution<> d(1, 14620);
std::mt19937 gen;
std::cout << d(gen) << '\n';
}
这将是快速,方便和高品质。
你没有指定,但如果你想浮点,而不是仅仅在子:
std::uniform_real_distribution<> d(1, 14620);
如果你需要一个非均匀分布,你可以建立自己的分段常数或piece-明智的线性分布很容易。
如前所述,您可以使用rand()。例如。
int n = rand() % 14620 + 1;
做的工作,但它是不均匀的。 这意味着一些值(低值)会稍微频繁出现。这是因为rand()
产生的值在0到RAND_MAX
之间,而RAND_MAX
通常不能被14620整除。如果是RAND_MAX == 15000
,那么数字1将是数字1000的两倍,因为rand() == 0
和rand() == 14620
都产生n==1
,但只有rand()==999
使得n==1000
为真。
但是,如果14620比RAND_MAX
小得多,这种影响可以忽略不计。在我的电脑RAND_MAX
等于2147483647.如果rand()
产生介于0和RAND_MAX之间的均匀样本,那么因为2147483647%14620 = 10327和2147483647/14620 = 146886,所以n
平均146887次会在1和10328之间,而10329和10329之间的数字如果您绘制2147483647个样本,则平均146886次会发生。 如果你问我,没什么区别。
但是,如果RAND_MAX == 15000
它将有所不同,如上所述。 在这种情况下,一些较早的帖子建议使用
int n = (int)(((((double)std::rand())/RAND_MAX) * 14620) + 1);
,使其“更加均匀”。 请注意,由于rand()
仍然只返回“仅”RAND_MAX
不同值,因此这只会更改频繁发生的数字。 为了使它真的一致,如果它在14620 * int(RAND_MAX/14620)和RAND_MAX之间的范围内并且再次呼叫rand()
,则必须拒绝任何整数形式rand()
。 在RAND_MAX == 15000
的示例中,您将拒绝14620和15000之间的rand()
的任何值并再次绘制。 对于大多数应用程序来说,这不是必需的。我更担心rand()
的随机性。
模运算符是最重要的,你可以申请限制,从而与此模量,检查了这一点:
// random numbers generation in C++ using builtin functions
#include <iostream>
using namespace std;
#include <iomanip>
using std::setw;
#include <cstdlib> // contains function prototype for rand
int main()
{
// loop 20 times
for (int counter = 1; counter <= 20; counter++) {
// pick random number from 1 to 6 and output it
cout << setw(10) << (1 + rand() % 6);
// if counter divisible by 5, begin new line of output
if (counter % 5 == 0)
cout << endl;
}
return 0; // indicates successful termination
} // end main
的rand()函数是不是真的是最好的随机数生成器,一个更好的方式是通过使用CryptGenRandom()。
这个例子应该做的伎俩:
#include <Windows.h>
// Random-Generator
HCRYPTPROV hProv;
INT Random() {
if (hProv == NULL) {
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_VERIFYCONTEXT))
ExitProcess(EXIT_FAILURE);
}
int out;
CryptGenRandom(hProv, sizeof(out), (BYTE *)(&out));
return out & 0x7fffffff;
}
int main() {
int ri = Random() % 14620 + 1;
}
你现在连仰望如何在C++中使用随机数?你也没有说明你是否需要一个更好的解决方案来建立在C++中的随机数字或者只是被告知如何使用rand。 – thecoshman 2011-02-16 17:28:33
你能澄清一下你的意思是“针对随机数生成的限制”,特定于C++吗?或多或少均匀的序列来自更好或更差的发生器。 – Francesco 2011-02-16 18:18:09
如果rand()是(可以是非均匀的),那么它没有多大用处。 – 2011-02-16 18:21:40