2013-01-01 109 views
1

我想在VS2010中使用模板来根据类型创建随机数。我使用下面的代码:浮点数/双精度浮点数的小范围,适用于整型(C++,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

您正在生成的值在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()之间的非负数,并分别生成其符号。

+0

那么我怎样才能使用全部范围的浮动/双打随机数生成? 谢谢, Oren –

+0

@OrenSarid:我以前的答案在这里错过了真正的问题。看到我编辑的答案。 – interjay