Joh*_*ing 363
rand()
可用于在C++中生成伪随机数.结合RAND_MAX
数学和小数学,您可以在您选择的任意间隔中生成随机数.这足以用于学习目的和玩具程序.如果您需要具有正态分布的真正随机数,则需要采用更高级的方法.
这将生成从0.0到1.0(包括0.0和1.0)的数字.
float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
Run Code Online (Sandbox Code Playgroud)
这将生成一个从0.0到任意的数字float
,X
:
float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));
Run Code Online (Sandbox Code Playgroud)
这将生成一些从任意LO
到任意的数字HI
:
float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));
Run Code Online (Sandbox Code Playgroud)
请注意,rand()
如果您需要真正的随机数,该功能通常是不够的.
在呼叫之前rand()
,您必须首先通过呼叫"播种"随机数生成器srand()
.这应该在程序运行期间完成一次 - 每次调用时都不会执行一次rand()
.这通常是这样做的:
srand (static_cast <unsigned> (time(0)));
Run Code Online (Sandbox Code Playgroud)
为了打电话rand
或srand
你必须#include <cstdlib>
.
为了打电话time
,你必须#include <ctime>
.
Sha*_*our 122
C++ 11为您提供了许多新选项random
.关于这个主题的规范性论文将是N3551,C++ 11中的随机数生成
要了解为什么使用rand()
可能会有问题,请参阅2013年GoingNative期间由Stephan T. Lavavej撰写的rand()Considered Harmful演示材料.幻灯片在评论中,但这里是直接链接.
我还介绍boost
和使用,rand
因为遗留代码可能仍然需要它的支持.
下面的示例是从cppreference站点提取的,并使用std :: mersenne_twister_engine引擎和std :: uniform_real_distribution,它在[0,10)
区间中生成数字,其他引擎和发行版已注释掉(请参见实时):
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
int main()
{
std::random_device rd;
//
// Engines
//
std::mt19937 e2(rd());
//std::knuth_b e2(rd());
//std::default_random_engine e2(rd()) ;
//
// Distribtuions
//
std::uniform_real_distribution<> dist(0, 10);
//std::normal_distribution<> dist(2, 2);
//std::student_t_distribution<> dist(5);
//std::poisson_distribution<> dist(2);
//std::extreme_value_distribution<> dist(0,2);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(e2))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
Run Code Online (Sandbox Code Playgroud)
输出将类似于以下内容:
0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****
Run Code Online (Sandbox Code Playgroud)
输出将根据您选择的分布有所不同,因此,如果我们决定一起去的std :: normal_distribution具有的价值2
的两种意思和STDDEV如dist(2, 2)
不是输出将与此类似(见直播):
-6
-5
-4
-3
-2 **
-1 ****
0 *******
1 *********
2 *********
3 *******
4 ****
5 **
6
7
8
9
Run Code Online (Sandbox Code Playgroud)
以下是一些代码的修改版本N3551
(现场直播):
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
std::default_random_engine & global_urng( )
{
static std::default_random_engine u{};
return u ;
}
void randomize( )
{
static std::random_device rd{};
global_urng().seed( rd() );
}
int main( )
{
// Manufacture a deck of cards:
using card = int;
std::array<card,52> deck{};
std::iota(deck.begin(), deck.end(), 0);
randomize( ) ;
std::shuffle(deck.begin(), deck.end(), global_urng());
// Display each card in the shuffled deck:
auto suit = []( card c ) { return "SHDC"[c / 13]; };
auto rank = []( card c ) { return "AKQJT98765432"[c % 13]; };
for( card c : deck )
std::cout << ' ' << rank(c) << suit(c);
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
结果将类似于:
5H 5S AS 9S 4D 6H TH 6D KH 2S QS 9H 8H 3D KC TD 7H 2D KS 3C TC 7D 4C QH QC QD JD AH JC AC KD 9D 5C 2H 4H 9C 8C JH 5D 4S 7C AD 3S 8S TS 2C 8D 3H 6C JS 7S 6S
促进
当然Boost.Random也是一个选项,这里我使用的是boost :: random :: uniform_real_distribution:
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
int main()
{
boost::random::mt19937 gen;
boost::random::uniform_real_distribution<> dist(0, 10);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(gen))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
Run Code Online (Sandbox Code Playgroud)
RAND()
如果你必须使用rand()
那么我们可以去C FAQ获取指南如何生成浮点随机数?,基本上给出了一个类似的例子,用于在间隔上生成[0,1)
:
#include <stdlib.h>
double randZeroToOne()
{
return rand() / (RAND_MAX + 1.);
}
Run Code Online (Sandbox Code Playgroud)
并生成以下范围内的随机数[M,N)
:
double randMToN(double M, double N)
{
return M + (rand() / ( RAND_MAX / (N-M) ) ) ;
}
Run Code Online (Sandbox Code Playgroud)
rlb*_*ond 60
看看Boost.Random.你可以这样做:
float gen_random_float(float min, float max)
{
boost::mt19937 rng;
boost::uniform_real<float> u(min, max);
boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
return gen();
}
Run Code Online (Sandbox Code Playgroud)
玩转,你可能会更好地传递相同的mt19937对象,而不是每次构建一个新对象,但希望你能得到这个想法.
Iva*_*nov 24
使用两个float
值调用代码,代码适用于任何范围.
float rand_FloatRange(float a, float b)
{
return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}
Run Code Online (Sandbox Code Playgroud)
And*_* DM 22
在现代,c++
您可以使用<random>
随附的标题c++11
.
要获得随机float
的,你可以使用std::uniform_real_distribution<>
.
您可以使用函数生成数字,如果您不希望数字始终相同,请将引擎和分布设置为 static
.
例:
float get_random()
{
static std::default_random_engine e;
static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
return dis(e);
}
Run Code Online (Sandbox Code Playgroud)
将它放在float
容器中是理想的,例如std::vector
:
int main()
{
std::vector<float> nums;
for (int i{}; i != 5; ++i) // Generate 5 random floats
nums.emplace_back(get_random());
for (const auto& i : nums) std::cout << i << " ";
}
Run Code Online (Sandbox Code Playgroud)
示例输出:
0.0518757 0.969106 0.0985112 0.0895674 0.895542
Run Code Online (Sandbox Code Playgroud)
Ric*_*ick 20
如果您使用的是C++而不是C,那么请记住,在技术报告1(TR1)和C++ 0x草案中,他们为头文件中的随机数生成器添加了工具,我相信它与Boost相同.随机库,肯定比C库函数更灵活和"现代",兰德.
此语法提供了选择生成器(如mersenne twister mt19937)然后选择分布(正常,bernoulli,二项式等)的功能.
语法如下(从本网站借来的无耻):
#include <iostream>
#include <random>
...
std::tr1::mt19937 eng; // a core engine class
std::tr1::normal_distribution<float> dist;
for (int i = 0; i < 10; ++i)
std::cout << dist(eng) << std::endl;
Run Code Online (Sandbox Code Playgroud)
在某些系统上(当前RAND_MAX
,我想到的是VC弹簧的Windows),非常小,我.即 只有15位.除以时,RAND_MAX
您只生成15位的尾数,而不是23位可能的位.这对您来说可能是也可能不是问题,但在这种情况下您错过了一些值.
哦,只是注意到已经有人对这个问题发表评论.无论如何,这里有一些代码可以解决这个问题:
float r = (float)((rand() << 15 + rand()) & ((1 << 24) - 1)) / (1 << 24);
Run Code Online (Sandbox Code Playgroud)
未经测试,但可能有效:-)