1

タイプに基づいた乱数の作成に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//など(整数型)のBaseTypeRandomizerのオブジェクトを作成すると、範囲全体をカバーする数値が返されますが、floatとdoubleの場合は返されません。フロートはすべてとの間にあり、ダブルはとの間にあります(または少なくともすべてがその近隣にあります)。VSデバッガーでオブジェクトをチェックすると、制限が正しいことがわかりますが、ベクトルははるかに狭い範囲の数値で埋められます。intlong1e+379e+381e+3072e+308distValues

制限が正しく機能しない理由を誰かが知っていますか?

4

1 に答える 1

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()を生成し、その符号を個別に生成できます。

于 2013-01-01T13:40:20.373 に答える