क्या बूस्ट का उपयोग कर नमूनों वाले वेक्टर के लिए माध्य और मानक विचलन की गणना करने का एक तरीका है ?
या क्या मुझे एक संचायक बनाना है और उसमें वेक्टर को खिलाना है?
क्या बूस्ट का उपयोग कर नमूनों वाले वेक्टर के लिए माध्य और मानक विचलन की गणना करने का एक तरीका है ?
या क्या मुझे एक संचायक बनाना है और उसमें वेक्टर को खिलाना है?
जवाबों:
संचायक का उपयोग बूस्ट में साधन और मानक विचलन की गणना करने का तरीका है ।
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;
second moment - squared mean
जो गलत परिणाम उत्पन्न करेगा यदि राउंडिंग त्रुटियों के कारण विचरण बहुत छोटा है। यह वास्तव में नकारात्मक विचरण पैदा कर सकता है।
मुझे नहीं पता कि बूस्ट में अधिक विशिष्ट कार्य हैं, लेकिन आप इसे मानक पुस्तकालय के साथ कर सकते हैं।
यह देखते हुए std::vector<double> v
, यह अनुभवहीन तरीका है:
#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);
यह विशाल या छोटे मूल्यों के लिए अतिप्रवाह या कम प्रवाह के लिए अतिसंवेदनशील है। मानक विचलन की गणना करने का थोड़ा बेहतर तरीका है:
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());
C ++ 11 के लिए अद्यतन :
और (अब पदावनत) के std::transform
बजाय एक लंबो फ़ंक्शन का उपयोग करके कॉल को लिखा जा सकता है :std::minus
std::bind2nd
std::transform(v.begin(), v.end(), diff.begin(), [mean](double x) { return x - mean; });
mean
शीर्ष भाग में गणना के मूल्य पर निर्भर करता है ।
(v.size() - 1)
के लिए v.size()
ऊपर अंतिम पंक्ति में: std::sqrt(sq_sum / (v.size() - 1))
। (पहली विधि के लिए, यह एक छोटे से जटिल है: std::sqrt(sq_sum / (v.size() - 1) - mean * mean * v.size() / (v.size() - 1))
।
std::inner_product
वर्गों का योग के लिए उपयोग बहुत साफ है।
यदि प्रदर्शन आपके लिए महत्वपूर्ण है, और आपका कंपाइलर लैम्ब्डा का समर्थन करता है, तो स्टदेव गणना को तेज और सरल बनाया जा सकता है: वीएस 2012 के साथ परीक्षणों में मैंने पाया है कि चुने गए उत्तर में दिए गए बूस्ट कोड की तुलना में निम्नलिखित कोड 10 एक्स तेज है। ; यह भी मुस्तफ़िल द्वारा दिए गए मानक पुस्तकालयों का उपयोग कर उत्तर के सुरक्षित संस्करण की तुलना में 5 एक्स तेज है।
नोट मैं नमूना मानक विचलन का उपयोग कर रहा हूं, इसलिए नीचे दिया गया कोड थोड़ा अलग परिणाम देता है ( मानक विचलन में एक शून्य क्यों है )
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));
std::end()
समारोह के मामलों के लिए सी ++ 11 मानक से जोड़ा गया है जब की तरह कुछ भी नहीं है वहाँ v.end()
। std::end
कम मानक कंटेनर के लिए अतिभारित किया जा सकता - देख en.cppreference.com/w/cpp/iterator/end
मुशीफिल द्वारा उत्तर पर सुधार , आप अस्थायी वेक्टर के बिना एक मानक विचलन फ़ंक्शन लिख सकते हैं diff
, बस inner_product
C ++ 11 लंबो क्षमताओं के साथ एक कॉल का उपयोग कर सकते हैं :
double stddev(std::vector<double> const & func)
{
double mean = std::accumulate(func.begin(), func.end(), 0.0) / func.size();
double sq_sum = std::inner_product(func.begin(), func.end(), func.begin(), 0.0,
[](double const & x, double const & y) { return x + y; },
[mean](double const & x, double const & y) { return (x - mean)*(y - mean); });
return std::sqrt(sq_sum / ( func.size() - 1 ));
}
मुझे संदेह है कि कई बार घटाव को अतिरिक्त मध्यवर्ती भंडारण का उपयोग करने से सस्ता है, और मुझे लगता है कि यह अधिक पठनीय है, लेकिन मैंने अभी तक प्रदर्शन का परीक्षण नहीं किया है।
ऐसा लगता है कि निम्नलिखित सुरुचिपूर्ण पुनरावर्ती समाधान का उल्लेख नहीं किया गया है, हालांकि यह लंबे समय से आसपास है। कंप्यूटर प्रोग्रामिंग के नथ की कला का जिक्र करते हुए,
mean_1 = x_1, variance_1 = 0; //initial conditions; edge case;
//for k >= 2,
mean_k = mean_k-1 + (x_k - mean_k-1) / k;
variance_k = variance_k-1 + (x_k - mean_k-1) * (x_k - mean_k);
फिर n>=2
मूल्यों की सूची के लिए , मानक विचलन का अनुमान है:
stddev = std::sqrt(variance_n / (n-1)).
उम्मीद है की यह मदद करेगा!
मेरा जवाब जोश ग्रीफर के समान है, लेकिन नमूना covariance के लिए सामान्यीकृत है। नमूना विचरण सिर्फ नमूना covariance है, लेकिन समान दो आदानों के साथ। इसमें बेसेल का सहसंबंध भी शामिल है।
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);
}
उल्लेख से पहले के संस्करणों की तुलना में तेजी से 2x - ज्यादातर क्योंकि रूपांतरण () और इनर_प्रोडक्ट () लूप्स में शामिल हो गए हैं। मेरे शॉर्टकट / टाइपफेड / मैक्रो के बारे में क्षमा करें: फ़्लोट = फ़्लोट। सीआर कास्ट रेफरी। VFlo - वेक्टर। VS2010 में परीक्षण किया गया
#define fe(EL, CONTAINER) for each (auto EL in CONTAINER) //VS2010
Flo stdDev(VFlo CR crVec) {
SZ n = crVec.size(); if (n < 2) return 0.0f;
Flo fSqSum = 0.0f, fSum = 0.0f;
fe(f, crVec) fSqSum += f * f; // EDIT: was Cit(VFlo, crVec) {
fe(f, crVec) fSum += f;
Flo fSumSq = fSum * fSum;
Flo fSumSqDivN = fSumSq / n;
Flo fSubSqSum = fSqSum - fSumSqDivN;
Flo fPreSqrt = fSubSqSum / (n - 1);
return sqrt(fPreSqrt);
}
for( float f : crVec ) { fSqSum += f * f; fSum += f; }
?
अपना खुद का कंटेनर बनाएँ:
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();
}
};
इसकी कुछ सीमाएँ हैं, लेकिन यह खूबसूरती से काम करता है जब आप जानते हैं कि आप क्या कर रहे हैं।
// का मतलब है c ++ में विचलन
/ एक विचलन जो एक मनाया मूल्य और ब्याज की मात्रा के सच्चे मूल्य के बीच अंतर है (जैसे कि जनसंख्या का मतलब) एक त्रुटि और एक विचलन है जो मनाया मूल्य और सच्चे मूल्य के अनुमान के बीच अंतर है (जैसे एक अनुमान एक नमूना मतलब हो सकता है) एक अवशिष्ट है। ये अवधारणाएं माप के अंतराल और अनुपात के स्तर पर डेटा के लिए लागू होती हैं। /
#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;
}