2012-10-24 42 views
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 *吨回事..

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,max:353488 5:size:8327571,min: -2.24712e + 307,max:139960 6:size:8327571,min:0,max:0 7:size:8327571,min:0,max:0 8:size:8327571,min:0,max:0 9:size: 8327571,min:0,max:0 10:size:8327571,min:0,max:0 11:size: 8327571,min:0 ,最多:0

+2

你可以总结'number [i]/n' - 但它可能会增加数字错误... – amit

+1

如果所有'Features-> size()'不是'0',你确定吗? (提示:任何浮点数,除以0将给你无穷大 - 如果该数字是非负数 - '1. INF#,如果它是负数 - '-1。#INF') –

+0

@PaulR它是一个错字,对不起。 – Stefan

回答

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; 
     } 
    } 
} 

你应该能够迅速发现,如果有什么奇怪与输入。

+1

+1。 *这不加起来* - 无论是字面上还是比喻上。有些数据有些奇怪。我怀疑一些数值尚未初始化。这些数字大概代表了物理的东西。无论是米,千克,#人,无论如何,其中10^300是垃圾价值。 –

+0

+1你们俩完全正确! 0:size:8327571,min:-2.24712e + 307,max:3362.12 1:size:8327571,min:-2.24712e + 307,max:142181 2:size:8327571,min:-2.24712e + 307 ,最大值:59537.8, 3:size:8327571,min:-2.24712e + 307,max:236815 4:size:8327571,min:-2.24712e + 307,max:353488 5:size:8327571,min: - 2.24712e + 307,max:139960 6:size:8327571,min:0,max:0 7:size:8327571,min:0,max:0 8:size:8327571,min:0,max:0 9:size:8327571,min:0,max:0 10:size:8327571,min:0,max:0 11:size:8327571,min:0,max:0 什么是一堆垃圾sh *对我很耻辱! – Stefan

+0

嗨,我现在已经“解决”了获取垃圾数据。阅读数据时出现了一些小错误。无论如何,我发现了一个奇怪的行为。用你的循环检查元素工作正常,并给我很好和平滑的数据。没有错误或垃圾值。但是如果我稍后总结它们,我会发现一个值在矢量-1。#IND ..中,但是在循环中将它推到值中不是。直接访问它与已知的索引我可以再次看到#IND ..疯狂? – Stefan

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,我从here得到它。

你也可以考虑使用大号码库。