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

我想我可以用整数rand除以某个数,这足够了吗?


当前回答

以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对象,而不是每次都构造一个新的对象,但希望您能理解。

其他回答

对于c++,它可以在dist变量指定的范围内生成实浮点数

#include <random>  //If it doesnt work then use   #include <tr1/random>
#include <iostream>

using namespace std;

typedef std::tr1::ranlux64_base_01 Myeng; 
typedef std::tr1::normal_distribution<double> Mydist;

int main() { 
       Myeng eng; 
       eng.seed((unsigned int) time(NULL)); //initializing generator to January 1, 1970);
       Mydist dist(1,10); 

       dist.reset(); // discard any cached values 
       for (int i = 0; i < 10; i++)
       {
           std::cout << "a random value == " << (int)dist(eng) << std::endl; 
       }

       return (0);
}

调用带有两个浮点值的代码,代码可以在任何范围内工作。

float rand_FloatRange(float a, float b)
{
    return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}

到目前为止,我对任何答案都不满意,所以我写了一个新的随机浮点函数。它对浮点数据类型进行了按位假设。它仍然需要一个rand()函数,至少有15个随机位。

//Returns a random number in the range [0.0f, 1.0f).  Every
//bit of the mantissa is randomized.
float rnd(void){
  //Generate a random number in the range [0.5f, 1.0f).
  unsigned int ret = 0x3F000000 | (0x7FFFFF & ((rand() << 8) ^ rand()));
  unsigned short coinFlips;

  //If the coin is tails, return the number, otherwise
  //divide the random number by two by decrementing the
  //exponent and keep going. The exponent starts at 63.
  //Each loop represents 15 random bits, a.k.a. 'coin flips'.
  #define RND_INNER_LOOP() \
    if( coinFlips & 1 ) break; \
    coinFlips >>= 1; \
    ret -= 0x800000
  for(;;){
    coinFlips = rand();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    //At this point, the exponent is 60, 45, 30, 15, or 0.
    //If the exponent is 0, then the number equals 0.0f.
    if( ! (ret & 0x3F800000) ) return 0.0f;
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
    RND_INNER_LOOP(); RND_INNER_LOOP(); RND_INNER_LOOP();
  }
  return *((float *)(&ret));
}

rand()返回一个介于0和RAND_MAX之间的int值。要获得0.0到1.0之间的随机数,首先将rand()返回的int转换为浮点数,然后除以RAND_MAX。

在我看来,上面的答案确实给出了一些“随机”浮点数,但它们都不是真正的随机浮点数(即它们错过了浮点数表示的一部分)。在我进入我的实现之前,让我们先看看浮点数的ANSI/IEEE标准格式:

|符号(1位)| e(8位)| f(23位)|

这个词代表的数字是 (-1 *号)* 2^e * 1.f

注意“e”是一个有偏差的数字(偏差为127),因此范围从-127到126。最简单的(实际上也是最随机的)函数是将随机int类型的数据写入浮点数,因此

int tmp = rand();
float f = (float)*((float*)&tmp);

注意,如果你做浮动f = (float)rand();它将整数转换为浮点数(因此10将变成10.0)。 现在如果你想限制最大值你可以这样做(不确定是否有效)

int tmp = rand();
float f = *((float*)&tmp);
tmp = (unsigned int)f       // note float to int conversion!
tmp %= max_number;
f -= tmp;

但是如果你观察浮点数的结构,你会发现浮点数的最大值大约是2^127,这比int数的最大值(2^32)要大得多,因此排除了很大一部分可以用浮点数表示的数字。 这是我的最终实现:

/**
 * Function generates a random float using the upper_bound float to determine 
 * the upper bound for the exponent and for the fractional part.
 * @param min_exp sets the minimum number (closest to 0) to 1 * e^min_exp (min -127)
 * @param max_exp sets the maximum number to 2 * e^max_exp (max 126)
 * @param sign_flag if sign_flag = 0 the random number is always positive, if 
 *              sign_flag = 1 then the sign bit is random as well
 * @return a random float
 */
float randf(int min_exp, int max_exp, char sign_flag) {
    assert(min_exp <= max_exp);

    int min_exp_mod = min_exp + 126;

    int sign_mod = sign_flag + 1;
    int frac_mod = (1 << 23);

    int s = rand() % sign_mod;  // note x % 1 = 0
    int e = (rand() % max_exp) + min_exp_mod;
    int f = rand() % frac_mod;

    int tmp = (s << 31) | (e << 23) | f;

    float r = (float)*((float*)(&tmp));

    /** uncomment if you want to see the structure of the float. */
//    printf("%x, %x, %x, %x, %f\n", (s << 31), (e << 23), f, tmp, r);

    return r;
}

使用这个函数randf(0,8,0)将返回一个介于0.0和255.0之间的随机数