c++ - creating full range of random floats using std::random -
i'm attempting test mathematical class i've created using random numbers full range of representable positivefloat
s, find seem having problem use of std::random
. program
#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'; (int i=0; < 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; }
produces output
range min = 1.17549e-38, max = 3.40282e+38 n = 1000000 sample min = 8.14884e+31, max = 3.40281e+38
clearly range extremely skewed toward larger numbers. how generate desired range of float
s uniform distribution?
in addition statistics have printed out, i've computed both theoretical , actual mean, variance, skew , kurtosis of this distribution. here code, , results:
#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'; (int i=0; < 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; (int = 0; < 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"; }
and here results:
range min = 1.17549e-38, max = 3.40282e+38 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
everything looking pretty me.
Comments
Post a Comment