4

我正在努力解决因不足或溢出而失败的求和问题。

我有超过 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:

所以你们中的一些人是完全正确的。有很多垃圾sh * t发生..

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, min: 0, max: 0 7: size: 8327571, min: 0, max: 0 8: size: 8327571, min: 0, max: 0 9: size: 8327571, min: 0 ,最大值:0 10:大小:8327571,最小值:0,最大值:0 11:大小:8327571,最小值:0,最大值:0

4

2 回答 2

4
  • 我有超过 8271571 个双精度值,我需要算术平均值。
  • 值的范围可能从我快速查看的范围,从 -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使用初始值调用,循环调用AddValue其余部分,完成后调用getMean.

这个想法来自 Knuth,我是从这里得到的。

您也可以考虑使用大数字库。

于 2012-10-24T14:38:18.390 回答