Я борюсь с проблемой суммирования, которая терпит неудачу с недостаточным или переполнением.
У меня более 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
- У меня более 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;
}
}
}
Вы должны быть в состоянии быстро определить, есть ли что-то странное с вводом.
Вы можете вычислить среднее значение с помощью онлайн-алгоритма, что означает, что вам не нужно добавлять все значения перед делением. Вот:
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
,
Эта идея от Кнута, и я получил ее от Вот.
Вы также можете рассмотреть возможность использования библиотеки больших чисел.