在c ++中生成随机双数

时间:2010-04-24 12:56:01

标签: c++ random

如何在c ++中的两个双打之间生成随机数,这些数字应该看起来像xxxxx,yyyyy。

8 个答案:

答案 0 :(得分:101)

以下是

double fRand(double fMin, double fMax)
{
    double f = (double)rand() / RAND_MAX;
    return fMin + f * (fMax - fMin);
}

每次程序启动时,请记住使用适当的种子调用srand()。

[编辑] 这个答案已经过时,因为C ++得到了它的原生非基于C的随机库(参见Alessandro Jacopsons的回答) 但是,这仍然适用于C

答案 1 :(得分:85)

此解决方案需要C ++ 11(或TR1)。

#include <random>

int main()
{
   double lower_bound = 0;
   double upper_bound = 10000;
   std::uniform_real_distribution<double> unif(lower_bound,upper_bound);
   std::default_random_engine re;
   double a_random_double = unif(re);

   return 0;
}

有关详细信息,请参阅John D. Cook的"Random number generation using C++ TR1"

另见Stroustrup的"Random number generation"

答案 2 :(得分:7)

如果精度是一个问题,你可以通过随机化有效位来创建更精细的随机数。 我们假设我们想要一个介于0.0和1000.0之间的双倍。

在MSVC(12 / Win32)上,RAND_MAX例如是32767。

如果您使用常见的rand()/RAND_MAX计划,您的差距将与

一样大
1.0 / 32767.0 * ( 1000.0 - 0.0) = 0.0305 ...

在IEE 754双变量(53个有效位)和53位随机化的情况下,0到1000问题的最小可能随机化间隙将是

2^-53 * (1000.0 - 0.0) = 1.110e-13

因此显着降低。

缺点是需要4次rand()调用才能获得随机整数(假设有15位RNG)。

double random_range (double const range_min, double const range_max)
{
  static unsigned long long const mant_mask53(9007199254740991);
  static double const i_to_d53(1.0/9007199254740992.0);
  unsigned long long const r( (unsigned long long(rand()) | (unsigned long long(rand()) << 15) | (unsigned long long(rand()) << 30) | (unsigned long long(rand()) << 45)) & mant_mask53 );
  return range_min + i_to_d53*double(r)*(range_max-range_min);
}

如果尾数或RNG的位数未知,则需要在函数内获得各自的值。

#include <limits>
using namespace std;
double random_range_p (double const range_min, double const range_max)
{
  static unsigned long long const num_mant_bits(numeric_limits<double>::digits), ll_one(1), 
    mant_limit(ll_one << num_mant_bits);
  static double const i_to_d(1.0/double(mant_limit));
  static size_t num_rand_calls, rng_bits;
  if (num_rand_calls == 0 || rng_bits == 0)
  {
    size_t const rand_max(RAND_MAX), one(1);
    while (rand_max > (one << rng_bits))
    {
      ++rng_bits;
    }
    num_rand_calls = size_t(ceil(double(num_mant_bits)/double(rng_bits)));
  }
  unsigned long long r(0);
  for (size_t i=0; i<num_rand_calls; ++i)
  {
    r |= (unsigned long long(rand()) << (i*rng_bits));
  }
  r = r & (mant_limit-ll_one);
  return range_min + i_to_d*double(r)*(range_max-range_min);
}

注意:我不知道所有平台上无符号长整数(64位)的位数是否大于双尾数位(IEE 754为53位)的数量。 如果情况并非如此,那么包括像if (sizeof(unsigned long long)*8 > num_mant_bits) ...这样的支票可能是“聪明的”。

答案 3 :(得分:4)

这应该是高性能,线程安全且足够灵活的,可用于多种用途:

#include <random>
#include <iostream>

template<typename Numeric, typename Generator = std::mt19937>
Numeric random(Numeric from, Numeric to)
{
    thread_local static Generator gen(std::random_device{}());

    using dist_type = typename std::conditional
    <
        std::is_integral<Numeric>::value
        , std::uniform_int_distribution<Numeric>
        , std::uniform_real_distribution<Numeric>
    >::type;

    thread_local static dist_type dist;

    return dist(gen, typename dist_type::param_type{from, to});
}

int main(int, char*[])
{
    for(auto i = 0U; i < 20; ++i)
        std::cout << random<double>(0.0, 0.3) << '\n';
}

答案 4 :(得分:2)

此片段直接来自Stroustrup的The C++ Programming Language (4th Edition),§40.7;它需要C ++ 11:

#include <functional>
#include <random>

class Rand_double
{
public:
    Rand_double(double low, double high)
    :r(std::bind(std::uniform_real_distribution<>(low,high),std::default_random_engine())){}

    double operator()(){ return r(); }

private:
    std::function<double()> r;
};

#include <iostream>    
int main() {
    // create the random number generator:
    Rand_double rd{0,0.5};

    // print 10 random number between 0 and 0.5
    for (int i=0;i<10;++i){
        std::cout << rd() << ' ';
    }
    return 0;
}

答案 5 :(得分:2)

为了生成随机数,我们可以使用其他朋友告诉的方法。我想在这里补充一个非常重要的点。

别人告诉的代码是:

//I have made this as a function that returns the random double value, just copy this
// if you want
double random(){
    return (double)rand() / RAND_MAX; // for generating random points between 0 to 1
}
//now suppose I want any random value between two numbers min and max then I can use this as :
int mynum = min + (max-min)*random();

但是这段代码的问题在于它是有偏见的,我的意思是它没有在 0 和 1 之间给出相等的值。 Click here to see the image 此图显示返回的值如何更偏向中心(即接近值 1)。为了避免这种情况,我们应该更喜欢以下代码:

double random(){
        return sqrt((double)rand() / RAND_MAX); // for generating random points between 0 to 1
    }

选择平方根函数的原因

选择 sqrt() 而不是像 cbrt() 这样的任何其他函数将其偏向外端的原因是,在上面提到的第一种方法中,生成的点与 R^2 成正比,因为我们的随机数与R,从而使圆的总面积与 R^2 成正比,使它们更集中于中心。使我们的随机数与 sqrt(R) 成正比将使在圆的所有面积上生成的点与 R 成正比,这将使所有点在整个圆中均匀生成。

请注意,在应用 sqrt([0, 1] 之间的点)后,结果将是一个大于原始 random() 的值,从而使其更偏向外端。这使得点在整个圆上均匀生成。

我要感谢 @archit91 在 this article

中分享有关 LeetCode 的有用信息

答案 6 :(得分:1)

已经有很多很棒的解决方案,而且很多都非常优雅。我只是想我会在列表中添加另一个。我直接从“现代 C++ 编程手册,第 2 版”中引用。在关于随机数生成器的章节中,有些强调正确初始化伪随机数生成器的重要性。它补充说,梅森扭曲器引擎倾向于重复生成某些值而不包括其他值,因此不会生成均匀分布的数字,而更像是二项式或泊松分布。我包含的代码片段完成了初始化生成器的步骤,以生成具有真正均匀分布的伪随机数。

auto generate_random_double(double lb, double ub)//lb= lowerbound, ub = upperbound
{
    //produce random #'s to be used as seeding values
    std::random_device rd{};

    //Generate random data for all the internal bits of the engine
    std::array<double, std::mt19937::state_size> seed_data{};
    ranges::generate(seed_data,std::ref(rd));
    
    //Create an std::seed_seq object from the pseudo random data 
    std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
    
    //Create an engine object and initialize the bits representing the internal      
    //state of the engine; form example an mt19937 has 19937 bits
    auto eng = std::mt19937{ seq };

    //Create object based on the approprieat distribution based on application   
    //requirments 
    const auto randDouble = std::uniform_real_distribution<>{ lb,ub };

    //return object seeded with the previously initialized object
    return randDouble(eng);

}//end method generate_random_double

答案 7 :(得分:0)

类似的东西:

#include <iostream>
#include <time.h>

using namespace std;

int main()
{
    const long max_rand = 1000000L;
    double x1 = 12.33, x2 = 34.123, x;

    srandom(time(NULL));

    x = x1 + ( x2 - x1) * (random() % max_rand) / max_rand;

    cout << x1 << " <= " << x << " <= " << x2 << endl;

    return 0;
}