Итак, я писал несколько раз, и раньше мои проблемы были довольно расплывчатыми. На этой неделе я начал заниматься C ++ и занимался небольшим проектом.

Я пытаюсь рассчитать стандартное отклонение и дисперсию. Мой код загружает файл из 100 целых чисел и помещает их в массив, считает их, вычисляет среднее значение, сумму, дисперсию и SD. Но у меня небольшие проблемы с дисперсией.

Я получаю огромное количество - мне кажется, дело в его подсчете.

Мое среднее и сумма в порядке.

NB:

sd & mean calcs

 using namespace std;
    int main()

{

int n = 0;
int Array[100];
float mean;
float var;
float sd;
string line;
float numPoints;

ifstream myfile("numbers.txt");

if (myfile.is_open())

{
    while (!myfile.eof())
      
    {
        getline(myfile, line);
            
        stringstream convert(line);
        
        if (!(convert >> Array[n]))
        
        {
            Array[n] = 0;
        }
        cout << Array[n] << endl;
        
        n++;
        
    }
    
    myfile.close();

    numPoints = n;

}
else cout<< "Error loading file" <<endl;

int sum = accumulate(begin(Array), end(Array), 0, plus<int>());

cout << "The sum of all integers: " << sum << endl;

mean = sum/numPoints;

cout << "The mean of all integers: " << mean <<endl;

var = ((Array[n] - mean) * (Array[n] - mean)) / numPoints;

sd = sqrt(var);

cout << "The standard deviation is: " << sd <<endl;

return 0;

}
13
Jack 21 Окт 2015 в 23:20

6 ответов

Лучший ответ

Как правильно предполагает другой ответ подковы, вам придется использовать цикл для вычисления дисперсии, иначе утверждение

var = ((Массив [n] - среднее значение) * (Массив [n] - среднее значение)) / numPoints;

Будет рассматривать только один элемент из массива.

Только что улучшенный код подковы:

var = 0;
for( n = 0; n < numPoints; n++ )
{
  var += (Array[n] - mean) * (Array[n] - mean);
}
var /= numPoints;
sd = sqrt(var);

Ваша сумма отлично работает даже без использования цикла, потому что вы используете функцию накопить , в которой уже есть цикл, но который не очевиден в коде, посмотрите на эквивалентное поведение накапливать для четкого понимания того, что он делает.

Примечание. X ?= Y - это сокращение от X = X ? Y, где ? может быть любым оператором. Также вы можете использовать pow(Array[n] - mean, 2), чтобы взять квадрат вместо того, чтобы умножать его на себя, делая его более аккуратным.

14
Ahmed Akhtar 13 Ноя 2018 в 06:21
#include <iostream>
#include <numeric>
#include <vector>
#include <cmath>
#include <utility>
#include <array>

template <class InputIterator, class T>
void Mean(InputIterator first, InputIterator last, T& mean) {
  int n = std::distance(first, last);
  mean = std::accumulate(first, last, static_cast<T>(0)) / n;
}

template <class InputIterator, class T>
void StandardDeviation(InputIterator first, InputIterator last, T& mean, T& stardard_deviation) {
  int n = std::distance(first, last);
  mean = std::accumulate(first, last, static_cast<T>(0)) / n;
  T s = std::accumulate(first, last, static_cast<T>(0), [mean](double x, double y) {
    T denta = y - mean;
    return x + denta*denta;
  });
  stardard_deviation = s/n;
}

int main () {
  std::vector<int> v = {10, 20, 30};

  double mean = 0;
  Mean(v.begin(), v.end(), mean);
  std::cout << mean << std::endl;

  double stardard_deviation = 0;
  StandardDeviation(v.begin(), v.end(), mean, stardard_deviation);
  std::cout << mean << " " << stardard_deviation << std::endl;

  double a[3] = {10.5, 20.5, 30.5};
  Mean(a, a+3, mean);
  std::cout << mean << std::endl;
  StandardDeviation(a, a+3, mean, stardard_deviation);
  std::cout << mean << " " << stardard_deviation << std::endl;

  std::array<int, 3> m = {1, 2, 3};
  Mean(m.begin(), m.end(), mean);
  std::cout << mean << std::endl;
  StandardDeviation(m.begin(), m.end(), mean, stardard_deviation);
  std::cout << mean << " " << stardard_deviation << std::endl;
  return 0;
}
0
manh duong 14 Авг 2020 в 12:21

Вместо того, чтобы писать больше циклов, вы можете создать функциональный объект для перехода к std::accumulate для вычисления среднего значения.

template <typename T>
struct normalize {
    T operator()(T initial, T value) {
        return initial + pow(value - mean, 2);
    }
    T mean;
}

Пока мы находимся в этом, мы можем использовать std :: istream_iterator для выполнения загрузка файла и std :: vector, потому что мы не знаем, сколько значения есть во время компиляции. Это дает нам:

int main()
{
    std::vector<int> values; // initial capacity, no contents yet

    ifstream myfile(“numbers.txt");
    if (myfile)
    {
        values.assign(std::istream_iterator<int>(myfile), {});
    }
    else { std::cout << "Error loading file" << std::endl; }

    float sum = std::accumulate(values.begin(), values.end(), 0, plus<int>()); // plus is the default for accumulate, can be omitted
    std::cout << "The sum of all integers: " << sum << std::endl;
    float mean = sum / values.size();
    std::cout << "The mean of all integers: " << mean << std::endl;
    float var = std::accumulate(values.begin(), values.end(), 0, normalize<float>{ mean }) / values.size();
    float sd = sqrt(var);
    std::cout << "The standard deviation is: " << sd << std::endl;
    return 0;
}
0
Caleth 9 Июл 2019 в 12:56

Два простых метода расчета стандартного отклонения и дисперсии в C ++.

#include <math.h>
#include <vector>

double StandardDeviation(std::vector<double>);
double Variance(std::vector<double>);

int main()
{
     std::vector<double> samples;
     samples.push_back(2.0);
     samples.push_back(3.0);
     samples.push_back(4.0);
     samples.push_back(5.0);
     samples.push_back(6.0);
     samples.push_back(7.0);

     double std = StandardDeviation(samples);
     return 0;
}

double StandardDeviation(std::vector<double> samples)
{
     return sqrt(Variance(samples));
}

double Variance(std::vector<double> samples)
{
     int size = samples.size();

     double variance = 0;
     double t = samples[0];
     for (int i = 1; i < size; i++)
     {
          t += samples[i];
          double diff = ((i + 1) * samples[i]) - t;
          variance += (diff * diff) / ((i + 1.0) *i);
     }

     return variance / (size - 1);
}
1
D.Zadravec 5 Мар 2017 в 22:54

Ваш расчет дисперсии находится вне цикла, и поэтому он основан только на n== 100 value.. Вам нужен дополнительный цикл.

Тебе нужно:

var = 0;
n=0;
while (n<numPoints){
   var = var + ((Array[n] - mean) * (Array[n] - mean));
   n++;
}
var /= numPoints;
sd = sqrt(var);
1
horseshoe 23 Окт 2015 в 06:48

Вот еще один подход с использованием std::accumulate, но без использования pow. Кроме того, мы можем использовать анонимную функцию, чтобы определить, как рассчитать дисперсию после вычисления среднего значения. Обратите внимание, что это вычисляет несмещенную дисперсию выборки.

#include <vector>
#include <algorithm>
#include <numeric>

template<typename T>
T variance(const std::vector<T> &vec) {
    const size_t sz = vec.size();
    if (sz == 1) {
        return 0.0;
    }

    // Calculate the mean
    const T mean = std::accumulate(vec.begin(), vec.end(), 0.0) / sz;

    // Now calculate the variance
    auto variance_func = [&mean, &sz](T accumulator, const T& val) {
        return accumulator + ((val - mean)*(val - mean) / (sz - 1));
    };

    return std::accumulate(vec.begin(), vec.end(), 0.0, variance_func);
}

Пример использования этой функции:

#include <iostream>
int main() {
    const std::vector<double> vec = {1.0, 5.0, 6.0, 3.0, 4.5};
    std::cout << variance(vec) << std::endl;
}
6
rayryeng 27 Сен 2020 в 07:41