在C ++中生成随机双精度数


80

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


6
“这些数字应类似于xxxxx,yyyyy”。如何生成随机双精度数以及如何将双精度数格式化为字符串是完全独立的问题。
史蒂夫·杰索普

并换一种方式来思考:生成均匀分布的双精度数和生成均匀分布的十进制数虽然有关联,但有些不同。
史蒂夫·杰索普

生成均匀分布的整数与小数点问题密切相关。
Potatoswatter

Answers:


115

就是这样

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

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

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


10
如果将1加到RAND_MAX,请谨慎操作,因为它可能等于INT_MAX。double f = rand() / (RAND_MAX + 1.0);
史蒂夫·杰索普

8
注意,可以限制其随机性。范围xxxxx,yyyyy表示10个十进制数字。许多系统中RAND_MAX小于10 ^ 10。这意味着该范围内的某些数字具有p(xxxxx,yyyyy)==0.0
MSalters 2010年

7
如果可能,应避免使用rand()。有关C ++ 11或TR1解决方案,请参见其他答案。
jfritz42 2014年

并非所有人都使用C ++ 0x,tr1或C ++ 11。是否有任何引用表明应避免使用rand()?这是几十年来获取随机数的唯一方法。
rep_movsd 2014年

1
@ChamilaWijayarathna,您需要包括cstdlib
Veridian 2015年

98

此解决方案需要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的“使用C ++ TR1生成随机数”

另请参见Stroustrup的“随机数生成”


7
您可能希望使用较新的cppreference文档进行更新,这非常好。
Shafik Yaghmour

9

对于许多用途,这应该是高性能的,线程安全的和足够灵活的:

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

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

注意:我不知道在所有平台上无符号long long(64位)的位数是否大于双尾数位数(IEE 754的53位)。if (sizeof(unsigned long long)*8 > num_mant_bits) ...如果不是这样的话,包括支票可能是“聪明的” 。


3

该摘录直接来自Stroustrup的The C ++ Programming Language(第4版),第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;
}

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

2
“((random()%max_rand)”“ =” random()“(即3%7 = 3)。这将是浪费的处理步骤。
Zak 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.