float / double的小范围随机数,适用于整数类型(C ++,VS2010)

时间:2013-01-01 12:40:47

标签: c++ visual-studio-2010 templates random numeric-limits

我正在尝试使用VS2010中的模板根据类型创建随机数。我使用下面的代码:

template<class BaseT>
struct distribution
{ // general case, assuming T is of integral type
    typedef std::tr1::uniform_int<BaseT> dist_type;
};

template<>
struct distribution<float>
{ // float case
    typedef std::tr1::uniform_real<float> dist_type;
};

template<>
struct distribution<double>
{ // double case
    typedef std::tr1::uniform_real_distribution<double> dist_type;
};

template<class BaseT>
class BaseTypeRandomizer
{
public:
    BaseTypeRandomizer() : mEngine(std::time(0))
    {
    }
    void CreateValues(std::vector<BaseT>& Values, size_t nValues)
    {
        typedef typename distribution<BaseT>::dist_type distro_type;
        std::random_device Engine;
        distro_type dist(std::numeric_limits<BaseT>::min(), std::numeric_limits<BaseT>::max());

        for (size_t iVal = 0; iVal < nValues; ++iVal)
        {
            Values[iVal] = dist(Engine);
        }
    }
};

不幸的是,为char / int / long等创建BaseTypeRandomizer的对象(整数类型)会返回覆盖整个范围的数字,但对于浮点数和双精度数,它们不会。浮动都在1e+379e+38之间,双打是1e+3072e+308(或者至少所有都在那个社区)。检查VS调试器中的dist对象会显示正确的限制,但Values向量会填充更小的数字范围。

有没有人知道为什么限制不能正常工作?

1 个答案:

答案 0 :(得分:1)

您正在生成numeric_limits<T>::min()numeric_limits<T>::max()之间的值。但numeric_limits<T>::min()可能不是您所期望的那样:对于浮点类型,它是最小标准化值,非常接近于零。所以你的代码只能获得正浮点数。对于float,这将是大约3.4e38的数字。绝大多数这些数字都超过1e37,所以你得到的结果大部分是有意义的。

要获得可能的有限值,您需要使用numeric_limits<T>::lowest()numeric_limits<T>::max()的范围。但这会导致未定义的行为,因为传递给uniform_real_distribution的范围大小必须达到numeric_limits<RealType>::max()

所以你需要以不同的方式生成数字。例如,您可以生成介于0和numeric_limits<T>::max()之间的非负数,并单独生成其符号。