使用std :: random创建全范围的随机浮点数

Edw*_*ard 3 c++ random c++11

我正在尝试使用来自全系列可表示的正数的随机数来测试我创建的数学课float,但我发现我似乎在使用时遇到了问题std::random.这个计划

#include <random>
#include <iostream>
#include <functional>

template <typename T>
class Rand {
public:
    Rand(T lo=std::numeric_limits<T>::min(), 
         T hi=std::numeric_limits<T>::max()) : 
        r(bind(std::uniform_real_distribution<>(lo, hi),std::mt19937_64{})) {}
    T operator()() const { return r(); }
private:
    std::function<T()> r;
};

int main()
{
    Rand<float> f{};
    const int samples = 1000000;
    float min = std::numeric_limits<float>::max();
    float max = std::numeric_limits<float>::min();
    std::cout << "range min = " << max 
        << ", max = " << min << '\n';
    for (int i=0; i < samples; ++i) {
        float r = f();
        if (r < min) min = r;
        if (r > max) max = r;
    }
    std::cout << "for n = " << samples 
        << "\nsample min = " << min 
        << ", max = " << max << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

产生这个输出

range min = 1.17549e-38, max = 3.40282e+38
for n = 1000000
sample min = 8.14884e+31, max = 3.40281e+38
Run Code Online (Sandbox Code Playgroud)

显然,范围极大地倾向于更大的数字.如何float以均匀分布生成所需的s 范围?

How*_*ant 5

除了你打印出来的统计数据外,我还计算了这个分布的理论和实际均值,方差,偏斜和峰度.这是我的代码,结果如下:

#include <random>
#include <iostream>
#include <functional>
#include <vector>
#include <numeric>
#include <cmath>

template <typename T>
class Rand {
public:
    Rand(T lo=std::numeric_limits<T>::min(), 
         T hi=std::numeric_limits<T>::max()) : 
        r(bind(std::uniform_real_distribution<>(lo, hi),std::mt19937_64{})) {}
    T operator()() const { return r(); }
private:
    std::function<T()> r;
};

template <class T>
inline
T
sqr(T x)
{
    return x * x;
}

int main()
{
    Rand<float> f{};
    const int samples = 1000000;
    float min = std::numeric_limits<float>::max();
    float max = std::numeric_limits<float>::min();
    std::vector<float> u;
    std::cout << "range min = " << max 
        << ", max = " << min << '\n';
    for (int i=0; i < samples; ++i) {
        float r = f();
        if (r < min) min = r;
        if (r > max) max = r;
        u.push_back(r);
    }
    std::cout << "for n = " << samples 
        << "\nsample min = " << min 
        << ", max = " << max << std::endl;
    double mean = std::accumulate(u.begin(), u.end(),
                                          double(0)) / u.size();
    double var = 0;
    double skew = 0;
    double kurtosis = 0;
    for (int i = 0; i < u.size(); ++i)
    {
        double d = (u[i] - mean);
        double d2 = sqr(d);
        var += d2;
        skew += d * d2;
        kurtosis += d2 * d2;
    }
    var /= u.size();
    double dev = std::sqrt(var);
    skew /= u.size() * dev * var;
    kurtosis /= u.size() * var * var;
    kurtosis -= 3;
    double x_mean = ((double)min + max) / 2;
    double x_var = sqr((double)max - min) / 12;
    double x_skew = 0;
    double x_kurtosis = -6./5;
    std::cout << std::scientific << '\n';
    std::cout << "            expected        actual\n";
    std::cout << "mean      " << x_mean     << "       " << mean << "\n";
    std::cout << "variance  " << x_var      << "       " << var << "\n";
    std::cout << "skew      " << x_skew     << "       " << skew << "\n";
    std::cout << "kurtosis  " << x_kurtosis << "       " << kurtosis << "\n";
}
Run Code Online (Sandbox Code Playgroud)

以下是结果:

range min = 1.17549e-38, max = 3.40282e+38
for n = 1000000
sample min = 8.14884e+31, max = 3.40281e+38

            expected        actual
mean      1.701407e+38       1.700724e+38
variance  9.649275e+75       9.645774e+75
skew      0.000000e+00       7.401975e-04
kurtosis  -1.200000e+00       -1.199432e+00
Run Code Online (Sandbox Code Playgroud)

一切对我来说都很好看.