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

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


当前回答

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

/* single precision float offers 24bit worth of linear distance from 1.0f to 0.0f */
float getval() {
    /* rand() has min 16bit, but we need a 24bit random number. */
    uint_least32_t r = (rand() & 0xffff) + ((rand() & 0x00ff) << 16);
    /* 5.9604645E-8 is (1f - 0.99999994f), 0.99999994f is the first value less than 1f. */
    return (double)r * 5.9604645E-8;
}

int main()
{
    srand(time(NULL));
...

我不能给出两个答案,所以这里是第二个答案。Log2随机数,很大程度上偏向于0.0f但它实际上是一个随机浮动1.0f到0.0f。

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

float getval () {
    union UNION {
        uint32_t i;
        float f;
    } r;
    /* 3 because it's 0011, the first bit is the float's sign.
     * Clearing the second bit eliminates values > 1.0f.
     */
    r.i = (rand () & 0xffff) + ((rand () & 0x3fff) << 16);
    return r.f;
}

int main ()
{
    srand (time (NULL));
...

其他回答

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

/* single precision float offers 24bit worth of linear distance from 1.0f to 0.0f */
float getval() {
    /* rand() has min 16bit, but we need a 24bit random number. */
    uint_least32_t r = (rand() & 0xffff) + ((rand() & 0x00ff) << 16);
    /* 5.9604645E-8 is (1f - 0.99999994f), 0.99999994f is the first value less than 1f. */
    return (double)r * 5.9604645E-8;
}

int main()
{
    srand(time(NULL));
...

我不能给出两个答案,所以这里是第二个答案。Log2随机数,很大程度上偏向于0.0f但它实际上是一个随机浮动1.0f到0.0f。

#include <cstdint>
#include <cstdlib>
#include <ctime>

using namespace std;

float getval () {
    union UNION {
        uint32_t i;
        float f;
    } r;
    /* 3 because it's 0011, the first bit is the float's sign.
     * Clearing the second bit eliminates values > 1.0f.
     */
    r.i = (rand () & 0xffff) + ((rand () & 0x3fff) << 16);
    return r.f;
}

int main ()
{
    srand (time (NULL));
...

在现代c++中,你可以使用c++11附带的<random>头文件。 要获得随机浮点数,可以使用std::uniform_real_distribution<>。

你可以使用一个函数来生成数字,如果你不希望数字总是相同的,那就将引擎和分布设置为静态。 例子:

float get_random()
{
    static std::default_random_engine e;
    static std::uniform_real_distribution<> dis(0, 1); // rage 0 - 1
    return dis(e);
}

理想的做法是将浮动对象放置在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 << " ";
}

示例输出:

0.0518757 0.969106 0.0985112 0.0895674 0.895542

如果您知道您的浮点数格式是IEEE 754(几乎所有现代cpu,包括Intel和ARM),那么您可以使用逐位方法从一个随机整数构建一个随机浮点数。只有当你无法访问c++ 11的random或Boost时,才应该考虑这样做。随机的,两者都更好。

float rand_float()
{
    // returns a random value in the range [0.0-1.0)

    // start with a bit pattern equating to 1.0
    uint32_t pattern = 0x3f800000;

    // get 23 bits of random integer
    uint32_t random23 = 0x7fffff & (rand() << 8 ^ rand());

    // replace the mantissa, resulting in a number [1.0-2.0)
    pattern |= random23;

    // convert from int to float without undefined behavior
    assert(sizeof(float) == sizeof(uint32_t));
    char buffer[sizeof(float)];
    memcpy(buffer, &pattern, sizeof(float));
    float f;
    memcpy(&f, buffer, sizeof(float));

    return f - 1.0;
}

这将比使用除法得到更好的分布。

drand48(3)是POSIX的标准方法。GLibC还提供了一个可重入版本drand48_r(3)。

该函数在SVID 3中被宣布过时,但没有提供足够的替代方案,因此IEEE Std 1003.1-2013仍然包含它,并且没有说明它将很快消失。

在Windows中,标准的方法是CryptGenRandom()。

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