C ++随机浮点数生成

如何在C ++中生成随机的浮点数?

我想我可以把整数兰德分成几个等级,这足够吗?


rand()可用于在C ++中生成伪随机数。 结合RAND_MAX和一些小数学运算,您可以根据您选择的任意间隔生成随机数。 这对于学习目的和玩具程序已经足够了。 如果您需要正态分布的真正随机数字,则需要采用更高级的方法。


这将生成一个从0.0到1.0的数字。

float r = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);

这将产生一个从0.0到某个任意floatX

float r2 = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/X));

这将从一些任意的LO生成一个数字到一些任意的HI

float r3 = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));

请注意,如果您需要真正的随机数, rand()函数通常是不够的。


在调用rand()之前,你必须首先通过调用srand() “随机生成”随机数生成器。 这应该在程序运行期间执行一次 - 不是每次调用rand()都执行一次。 这通常是这样做的:

srand (static_cast <unsigned> (time(0)));

为了调用randsrand你必须#include <cstdlib>

为了调用time ,你必须#include <ctime>


C ++ 11为您提供了许多random的新选项。 关于这个主题的标准论文将是N3551,C ++ 11中的随机数生成

要了解为什么使用rand()可能会有问题,请参阅2013年GoingNative活动期间提供的Stephan T. Lavavej提供的rand()有害演示材料。 幻灯片在评论中,但这里是直接链接。

我还介绍了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';
    }
}

输出将类似于以下内容:

0 ****
1 ****
2 ****
3 ****
4 *****
5 ****
6 *****
7 ****
8 *****
9 ****

输出将根据您选择的分布而变化,所以如果我们决定以std :: normal_distribution的值为2来表示mean和stddev,例如dist(2, 2)则输出将与此类似(请参阅生活):

-6 
-5 
-4 
-3 
-2 **
-1 ****
 0 *******
 1 *********
 2 *********
 3 *******
 4 ****
 5 **
 6 
 7 
 8 
 9 

以下是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;
}

结果看起来类似于:

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';
    }
}

RAND()

如果你必须使用rand()那么我们可以去C FAQ的一个指南如何生成浮点随机数? ,它基本上给出了一个类似于这样的例子来生成一个区间[0,1)

#include <stdlib.h>

double randZeroToOne()
{
    return rand() / (RAND_MAX + 1.);
}

并在[M,N)范围内生成一个随机数:

double randMToN(double M, double N)
{
    return M + (rand() / ( RAND_MAX / (N-M) ) ) ;  
}

看看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();
}

游玩一下,你可能会更好地传递相同的mt19937对象,而不是每次都创建一个新对象,但希望你能明白。

链接地址: http://www.djcxy.com/p/96727.html

上一篇: C++ random float number generation

下一篇: Vert.x: correctly stream to http response in case of closed client connection