2013-01-01 2 views
1

형식을 기준으로 난수 생성을 위해 VS2010에서 템플릿을 사용하려고합니다. char/int/long 등 (정수형) 전체 범위를 커버 번호를 반환하기위한 BaseTypeRandomizer의 객체를 생성, 불행하게도float/double에 대한 작은 범위의 난수, 정수형 (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); 
     } 
    } 
}; 

하지만, 수레와 복식에 대한 그들은하지 않습니다 : 나는 아래의 코드를 사용하고 있습니다. 부유물은 모두 1e+37에서 9e+38 사이이며, 복식은 1e+307에서 2e+308까지입니다 (또는 적어도 모두 해당 지역에 있음). VS 디버거에서 dist 개체를 검사하면 올바른 제한이 표시되지만 Values 벡터는 훨씬 작은 범위의 숫자로 채워집니다.

한계가 제대로 작동하지 않는 이유에 대해 누구나 알고 있습니까?

답변

1

numeric_limits<T>::min()numeric_limits<T>::max() 사이의 값을 생성 중입니다. 하지만 numeric_limits<T>::min()은 아마도 다음과 같을 것입니다. 부동 소수점 형식의 경우, 양수로 정규화 된 값은 0에 매우 가깝습니다. 따라서 코드는 양의 부동 소수점 수만 가져올 수 있습니다. 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

그럼 난수 생성을 위해 float/double 형식의 전체 범위를 어떻게 사용할 수 있습니까? 감사합니다, Oren –

+0

@OrenSarid : 이전의 대답은 여기서 진짜 문제를 놓쳤습니다. 내 편집 된 답변보기 – interjay