web-dev-qa-db-fra.com

Calcul de l'écart type et de la variance en C++

donc j'ai posté à quelques reprises et auparavant mes problèmes étaient assez vagues

j'ai commencé le C++ cette semaine et je fais un petit projet

donc j'essaie de calculer l'écart-type et la variance

mon code charge un fichier de 100 entiers et les met dans un tableau, les compte, calcs mean, sum, var et sd

mais j'ai un peu de mal avec la variance

je continue à avoir un nombre énorme - j'ai l'impression que c'est à voir avec son calcul

ma moyenne et ma somme sont ok

une aide ou des conseils?

NB:

 sd & mean calcs

À votre santé,

Jack

 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;

}
5
Jack

Comme le suggère correctement l’autre réponse de Horseshoe, vous devrez utiliser une boucle pour calculer la variance, sinon l’affirmation

var = ((Tableau [n] - moyenne) * (Tableau [n] - moyenne))/numPoints;

considérera simplement un seul élément du tableau.

Juste amélioré le code suggéré de fer à cheval:

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

Votre somme fonctionne bien même sans utiliser de boucle, car vous utilisez accumulate une fonction qui contient déjà une boucle, mais qui n'est pas évidente dans le code. Examinez le comportement équivalent de accumulate pour une compréhension claire de ce qu'il fait.

Remarque: X ?= Y est l'abréviation de X = X ? Y, où ? peut être n'importe quel opérateur. Aussi, vous pouvez utiliser pow(Array[n] - mean, 2) pour prendre le carré au lieu de le multiplier par lui-même, le rendant ainsi plus ordonné.

11
Ahmed Akhtar

Deux méthodes simples pour calculer la déviation standard et la variance en 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

Votre calcul de variance est en dehors de la boucle et il est donc basé uniquement sur le n== 100 value. Vous avez besoin d'une boucle supplémentaire.

Vous avez besoin:

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

Voici une autre approche utilisant std::accumulate mais sans utiliser pow. En outre, nous pouvons utiliser une fonction anonyme pour définir le mode de calcul de la variance après le calcul de la moyenne. Notez que ceci calcule la variance non biaisée de l'échantillon.

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

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

    // Calculate the mean
    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);
}

Un exemple d'utilisation de cette fonction:

int main()
{
    std::vector<double> vec = {1.0, 5.0, 6.0, 3.0, 4.5};
    std::cout << variance(vec) << std::endl;
}
0
rayryeng

Plutôt que d’écrire plus de boucles, vous pouvez créer un objet function à transmettre à std::accumulate pour calculer la moyenne.

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

Pendant que nous y sommes, nous pouvons utiliser std :: istream_iterator pour charger le fichier et std :: vector car nous ne savons pas combien de valeurs il y a au moment de la compilation. Cela nous donne:

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

    ifstream myfile(“numbers.txt");
    if (myfile.is_open())
    {
        std::copy(std::istream_iterator<int>(myfile), std::istream_iterator<int>(), std::back_inserter(values));
        myfile.close();
    }
    else { cout<< "Error loading file" <<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 });
    float sd = sqrt(var);
    std::cout << "The standard deviation is: " << sd << std::endl;
    return 0;
}
0
Caleth