4

アンダーまたはオーバーフローで失敗する合計の問題に取り組んでいます。

算術平均が必要な double 値が 8271571 個あります。

しかし、主な問題は、私がこれを行うほど頭が良くないように見えることです.

現在、それらを合計してサイズで割っています。これはほとんどの場合、アンダーまたはオーバーフローで失敗し、-1.#INF または 1.#INF になります。

for(size_t j = 0; j < 12; j++)
{
    double a = 0.0;

    for(size_t i=0; i < Features->size(); i++)
    {
        a += Features->at(i)->at(j);
    }
    meanVector[j] = a / Features->size();
}

ただし、正または負の値だけを言う可能性はないため、データ型を署名付きに設定することはできません。

また、それらを合計するときに、合計またはサイズで除算する際に除算定数を使用しようとしましたが、それも役に立ちません。

値は、私がざっと見ただけで -20 から +30 までの範囲である可能性がありますが、それを確実に言うことはできません。

そのため、誰かが計算方法や回避策のヒントを教えてくれるかもしれません。これはできるはずですが、アイデアが不足しています。

編集:

サイズが 0 になることはありません。チェックは分割の前で行われます。さらに、どの値も無効ではありません。それらを抽出している間、私はすでに#INDとNaNをチェックしています。

足し算で割ったら、これも正解じゃないのかな?

a+= Features->at(i)->at(j) / Features->size()

結果は -3.7964983860343639e+305

しかし、反復ごとに。これは正しくありません。境界のように見えます

編集2:

それで、あなたの何人かは完全に正しかった。たくさんのゴミが起こっています..

0: サイズ: 8327571、最小: -2.24712e+307、最大: 3362.12 1: サイズ: 8327571、最小: -2.24712e+307、最大: 142181 2: サイズ: 8327571、最小: -2.24712e+307、最大: 59537.8 3: サイズ: 8327571、最小: -2.24712e+307、最大: 236815 4: サイズ: 8327571、最小: -2.24712e+307、最大: 353488 5: サイズ: 8327571、最小: -2.24712e+307、最大: 139960 6: サイズ: 8327571、最小: 0、最大: 0 7: サイズ: 8327571、最小: 0、最大: 0 8: サイズ: 8327571、最小: 0、最大: 0 9: サイズ: 8327571、最小: 0 、最大: 0 10: サイズ: 8327571、最小: 0、最大: 0 11: サイズ: 8327571、最小: 0、最大: 0

4

2 に答える 2

4
  • 算術平均が必要な8271571を超えるdouble値があります。
  • 値は、私がざっと見たものから-20から+30までの範囲である可能性がありますが、それを確実に言うことはできません。
  • サイズが0になることはなく、部門の前で検査が行われます。

これは合計されません。double合計は簡単に収まるはずです。データに何か問題があるはずです。次のように、値をすばやく確認できます。

for (size_t j = 0; j < 12; ++j)
{
    std::vector<double> values;

    values.reserve(Features->size());
    for (size_t i = 0; i < Features->size(); ++i)
    {
        values.push_back(Features->at(i)->at(j));
    }

    // Find extreme values, including infinity
    std::cout << j << ": " 
              << "size: " << values.size() 
              << ", min: " << *std::min_element(values.begin(), values.end())
              << ", max: " << *std::max_element(values.begin(), values.end())
              << std::endl;

    // Find NaNs
    for (size_t i = 0; i < Features->size(); ++i)
    {
        // Choose one of the following ifs

        // For C++11 (isnan is a standard thing now)
        if (std::isnan(Features->at(i)->at(j))

        // Or for Visual Studio
        if (_isnan(Features->at(i)->at(j))

        // Or for GCC prior to C++11
        if (__builtin_isnan(Features->at(i)->at(j))

        {
            std::cout << "NaN at [" << i << ", " << j << "]" << std::endl;
        }
    }
}

入力に何か奇妙なことがあるかどうかをすばやく見つけることができるはずです。

于 2012-10-24T14:46:20.783 に答える
0

オンライン アルゴリズムを使用して平均を計算できます。つまり、除算する前にすべての値を加算する必要はありません。ここ:

template< typename NumberType >
class ProgressiveMean{
    NumberType  m_Mean;
    NumberType  m_MeanKMinus1;
    long        m_K;
public:
    ProgressiveMean();
    void Seed( NumberType seed );
    void AddValue( NumberType newVal );
    NumberType getMean() const;
};

template< typename NumberType >
ProgressiveMean<NumberType>::ProgressiveMean():
    m_Mean( 0 ),
    m_MeanKMinus1( 0 ),
    m_K( 0 ){
}

template< typename NumberType >
void ProgressiveMean<NumberType>::Seed( NumberType seed ){
    m_MeanKMinus1 = seed
    m_K = 2;  //Start from K = 1, so next one is 2
}

template< typename NumberType >
void ProgressiveMean<NumberType>::AddValue( NumberType newVal ){
    m_Mean = m_MeanKMinus1 + (newVal - m_MeanKMinus1) / m_K;
    m_MeanKMinus1 = m_Mean;
    m_K++;
}

template< typename NumberType >
NumberType ProgressiveMean<NumberType>::getMean() const{
    return m_Mean;
}

これを使用するには、初期値で呼び出し、残りのSeed呼び出しをループし、終了したら を呼び出します。AddValuegetMean

このアイデアは Knuth からのもので、ここから入手しました。

大きな数のライブラリの使用を検討することもできます。

于 2012-10-24T14:38:18.390 に答える