Pertanyaan Hitung rata-rata dan standar deviasi dari vektor sampel di C + + menggunakan Boost


Apakah ada cara untuk menghitung mean dan standar deviasi untuk vektor yang mengandung sampel yang digunakan Dorongan?

Atau apakah saya harus membuat akumulator dan memberi makan vektor ke dalamnya?


75
2017-09-30 21:59


asal


Jawaban:


Menggunakan akumulator aku s cara menghitung sarana dan standar deviasi dalam Dorongan.

accumulator_set<double, stats<tag::variance> > acc;
for_each(a_vec.begin(), a_vec.end(), bind<void>(ref(acc), _1));

cout << mean(acc) << endl;
cout << sqrt(variance(acc)) << endl;


42
2017-09-30 22:48



Saya tidak tahu apakah Boost memiliki fungsi yang lebih spesifik, tetapi Anda dapat melakukannya dengan pustaka standar.

Diberikan std::vector<double> v, ini adalah cara naif:

#include <numeric>

double sum = std::accumulate(v.begin(), v.end(), 0.0);
double mean = sum / v.size();

double sq_sum = std::inner_product(v.begin(), v.end(), v.begin(), 0.0);
double stdev = std::sqrt(sq_sum / v.size() - mean * mean);

Ini rentan terhadap limpahan atau underflow untuk nilai-nilai besar atau kecil. Cara yang sedikit lebih baik untuk menghitung standar deviasi adalah:

double sum = std::accumulate(v.begin(), v.end(), 0.0);
double mean = sum / v.size();

std::vector<double> diff(v.size());
std::transform(v.begin(), v.end(), diff.begin(),
               std::bind2nd(std::minus<double>(), mean));
double sq_sum = std::inner_product(diff.begin(), diff.end(), diff.begin(), 0.0);
double stdev = std::sqrt(sq_sum / v.size());

MEMPERBARUI untuk C ++ 11:

Panggilan ke std::transform dapat ditulis menggunakan fungsi lambda, bukan std::minus dan std::bind2nd(sekarang tidak lagi digunakan):

std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; });

175
2017-09-30 22:42



Jika kinerja penting bagi Anda, dan kompiler Anda mendukung lambdas, perhitungan stdev dapat dibuat lebih cepat dan lebih sederhana: Dalam tes dengan VS 2012 saya telah menemukan bahwa kode berikut ini lebih dari 10 X lebih cepat daripada kode Boost yang diberikan dalam jawaban yang dipilih ; itu juga 5 X lebih cepat daripada versi jawaban yang lebih aman menggunakan pustaka standar yang diberikan oleh musiphil.

Catatan Saya menggunakan standar deviasi sampel, sehingga kode di bawah ini memberikan hasil yang sedikit berbeda (Mengapa ada Minus One dalam Standar Deviasi)

double sum = std::accumulate(std::begin(v), std::end(v), 0.0);
double m =  sum / v.size();

double accum = 0.0;
std::for_each (std::begin(v), std::end(v), [&](const double d) {
    accum += (d - m) * (d - m);
});

double stdev = sqrt(accum / (v.size()-1));

53
2017-09-13 12:01



Jawaban saya mirip dengan Josh Greifer tetapi digeneralisasikan untuk sampel kovarian. Varians sampel hanyalah sampel kovarian tetapi dengan dua input identik. Ini termasuk korelasi Bessel.

    template <class Iter> typename Iter::value_type cov(const Iter &x, const Iter &y)
    {
        double sum_x = std::accumulate(std::begin(x), std::end(x), 0.0);
        double sum_y = std::accumulate(std::begin(y), std::end(y), 0.0);

        double mx =  sum_x / x.size();
        double my =  sum_y / y.size();

        double accum = 0.0;

        for (auto i = 0; i < x.size(); i++)
        {
            accum += (x.at(i) - mx) * (y.at(i) - my);
        }

        return accum / (x.size() - 1);
    }

1
2018-04-22 12:38



2x lebih cepat dari versi sebelum disebutkan - kebanyakan karena transform () dan inner_product () loop digabungkan. Maaf tentang pintas / typedefs / makro saya: Flo = float. Cit = const iteration. CR const ref. VFlo - vektor. Diuji dalam VS2010

Flo     stdDev2(VFlo CR crVec) {
    SZ  n = crVec.size();                               if (n < 2) return 0.0f;
    Flo fSqSum = 0.0f, fSum = 0.0f;
    Cit(VFlo, crVec) {
        Flo f   = *cx;
        fSqSum  += f * f; 
        fSum    += f;
    } 
    Flo fSumSq      = fSum * fSum;
    Flo fSumSqDivN  = fSumSq / n;
    Flo fSubSqSum   = fSqSum - fSumSqDivN;
    Flo preSqrt     = fSubSqSum / (n-1);
    return  sqrt(preSqrt);
}

0
2017-10-25 02:46



Buat penampung Anda sendiri:

template <class T>
class statList : public std::list<T>
{
    public:
        statList() : std::list<T>::list() {}
        ~statList() {}
        T mean() {
           return accumulate(begin(),end(),0.0)/size();
        }
        T stddev() {
           T diff_sum = 0;
           T m = mean();
           for(iterator it= begin(); it != end(); ++it)
               diff_sum += ((*it - m)*(*it -m));
           return diff_sum/size();
        }
};

Itu memang memiliki beberapa keterbatasan, tetapi ia bekerja dengan indah ketika Anda tahu apa yang Anda lakukan.


-2
2017-08-08 22:50



// berarti penyimpangan dalam c ++

/Penyimpangan yang merupakan perbedaan antara nilai yang diamati dan nilai sebenarnya dari kuantitas bunga (seperti rata-rata populasi) adalah kesalahan dan penyimpangan yang merupakan perbedaan antara nilai yang diamati dan perkiraan nilai sebenarnya (seperti perkiraan mungkin mean sampel) adalah residual. Konsep-konsep ini berlaku untuk data pada interval dan tingkat rasio pengukuran./

#include <iostream>
#include <conio.h>
using namespace std;

/* run this program using the console pauser or add your own getch,     system("pause") or input loop */

int main(int argc, char** argv)
{
int i,cnt;
cout<<"please inter count:\t";
cin>>cnt;
float *num=new float [cnt];
float   *s=new float [cnt];
float sum=0,ave,M,M_D;

for(i=0;i<cnt;i++)
{
    cin>>num[i];
    sum+=num[i];    
}
ave=sum/cnt;
for(i=0;i<cnt;i++)
{
s[i]=ave-num[i];    
if(s[i]<0)
{
s[i]=s[i]*(-1); 
}
cout<<"\n|ave - number| = "<<s[i];  
M+=s[i];    
}
M_D=M/cnt;
cout<<"\n\n Average:             "<<ave;
cout<<"\n M.D(Mean Deviation): "<<M_D;
getch();
return 0;

}


-6
2017-08-07 08:24