随机数发生器,C++

随机数发生器,C++

问题描述:

我知道C++中的随机数生成有一些限制(可以是非均匀的)。我怎样才能从1到14620产生一个数字?随机数发生器,C++

谢谢。

+0

你现在连仰望如何在C++中使用随机数?你也没有说明你是否需要一个更好的解决方案来建立在C++中的随机数字或者只是被告知如何使用rand。 – thecoshman 2011-02-16 17:28:33

+0

你能澄清一下你的意思是“针对随机数生成的限制”,特定于C++吗?或多或少均匀的序列来自更好或更差的发生器。 – Francesco 2011-02-16 18:18:09

+0

如果rand()是(可以是非均匀的),那么它没有多大用处。 – 2011-02-16 18:21:40

一种常见的方法是使用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() == 0rand() == 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; 
}