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:
À 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;
}
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é.
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);
}
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);
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;
}
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;
}