web-dev-qa-db-ja.com

C ++での標準偏差と分散の計算

何度か投稿しましたが、以前は問題がかなりあいまいでした

今週C++を始めて、小さなプロジェクトをやっています

標準偏差と分散を計算しようとしています

私のコードは100個の整数のファイルをロードして配列に入れ、それらを数え、平均、合計、変数、sdを計算します

しかし、私は分散に少し問題があります

私は膨大な数を得続けています-私はそれがその計算に関係していると感じています

私の平均と合計は大丈夫です

ヘルプやヒントはありますか?

注意:

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;

}
9
Jack

ホースシューによる他の答えが正しく示唆しているように、ループを使用して分散を計算する必要があります。

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

配列から単一の要素を考慮するだけです。

ホースシューの提案されたコードを改善しました:

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

accumulate関数を使用しているため、ループを使用しなくても合計は正常に機能します。この関数にはすでにループが含まれていますが、コードでは明らかではありません。 accumulate の同等の動作を見て、それが何をしているかを明確に理解してください。

注:_X ?= Y_は_X = X ? Y_の短縮形で、_?_は任意の演算子です。また、pow(Array[n] - mean, 2)を使用して、それ自体を掛け算する代わりに正方形を取り、整頓することもできます。

13
Ahmed Akhtar

std::accumulateを使用するがpowを使用しない別のアプローチを次に示します。さらに、無名関数を使用して、平均を計算した後で分散を計算する方法を定義できます。これは、不偏標本分散を計算することに注意してください。

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

この関数の使用方法のサンプル:

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

C++で標準偏差と分散を計算する2つの簡単な方法。

#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

分散計算はループの外にあるため、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

さらに多くのループを作成するのではなく、_ 関数オブジェクト を作成して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