标准差,方差 - 百度文库 (baidu.com)
定义: 算术平均数是指在一组数据中所有数据之和再除以数据的个数。它是反映数据集中趋势的一项指标。
公式为: x ˉ = x 1 + x 2 + ⋯ + x n n = ∑ i = 1 n x ÷ n \bar x = \frac{x_1 + x_2 + \cdots + x_n}n = \sum \limits_{i=1} ^n x ÷ n xˉ=nx1+x2+⋯+xn=i=1∑nx÷n
算术平均数是加权平均数的一种特殊情况,即各项的权相等时,加权平均数就是算术平均数。
定义: n个正实数乘积的n次算术根。给定n个正实数 a1,a2,…,an,其几何平均数为(a1a2……an)(1/n)。特别是,两个正数a,b的几何平均数c=(a*b)(1/2)是a与b的比例中项。任意n个正数a1,a2 ,…,an的几何平均数不大于这n个数的算术平均数,即(a1a2*……*an)^(1/n)≤(a1+a2+…+an)/n 。这个不等式在研究其他不等式或极值等问题时常起特殊作用。
定义:样本中各数据与样本平均数的差的平方和的平均数叫做样本方差;
样本方差和样本标准差都是衡量一个样本波动大小的量,样本方差或样本标准差越大,样本数据的波动就越大。
方差公式:
S 2 = 1 n [ ( x 1 − x ˉ ) 2 + ( x 2 − x ˉ ) 2 + ⋯ + ( x n − x ˉ ) 2 ] = 1 n ⋅ ∑ i = 1 n ( x i − x ˉ ) 2 (1) S^2 = \frac1n[(x_1 - \bar x)^2 + (x_2 - \bar x)^2 + \cdots + (x_n - \bar x)^2] = \frac 1 n \cdot \sum \limits_{i=1} ^ n(x_i - \bar x) ^2 \tag 1 S2=n1[(x1−xˉ)2+(x2−xˉ)2+⋯+(xn−xˉ)2]=n1⋅i=1∑n(xi−xˉ)2(1)
方差公式进一步推演,可以得出一个很适合编程的公式,如下:
S 2 = 1 n ⋅ ∑ i = 1 n ( x i − x ˉ ) 2 = 1 n ∑ i = 1 n x i 2 − 2 n x ˉ ∑ i = 1 n x i + n n x ˉ 2 = 1 n ⋅ ∑ i = 1 n x i 2 − 2 x ˉ 2 + x ˉ 2 = 1 n ⋅ ∑ x i 2 − x ˉ 2 (2) \begin{aligned} S^2 &= \frac 1n \cdot \sum \limits _{i=1} ^n (x_i - \bar x)^2 \\ &= \frac 1n \sum \limits _{i=1} ^n x_i ^2 - \frac2n \bar x \sum \limits _{i=1} ^n x_i + \frac nn \bar x ^2 \\ &= \frac 1n \cdot \sum \limits _{i=1} ^n x_i ^2 - 2 \bar x^2 + \bar x^2 \\ &= \frac 1n \cdot \sum x_i ^2 - \bar x ^ 2 \tag 2 \end{aligned} S2=n1⋅i=1∑n(xi−xˉ)2=n1i=1∑nxi2−n2xˉi=1∑nxi+nnxˉ2=n1⋅i=1∑nxi2−2xˉ2+xˉ2=n1⋅∑xi2−xˉ2(2)
最后的结果比较适合编程使用:
公式变成了只要求取 每个元素的平方之和 以及 所有元素的平均值,一个循环就能搞定。
摘自 :《C++程序设计教程(第二版) 习题及解答 钱能 习题练习题答案》
定义:样本方差的算术平方根叫做样本标准差,常称作均方差
由于方差是数据的平方,与检测值本身相差太大,人们难以直观的衡量,所以常用方差开根号换算回来这就是我们要说的标准差。
S = 1 n ⋅ ∑ i = 1 n ( x i − x ˉ ) 2 (3) S = \sqrt {\frac 1 n \cdot \sum \limits_{i=1} ^ n(x_i - \bar x) ^2} \tag{3} S=n1⋅i=1∑n(xi−xˉ)2(3)
定义一个数组,数据为:6, 3, 7, 1, 4, 8, 2, 9, 11, 5。请创建一个向量,把数组的初值赋给它,然后对该向量求标准差(均方差),即公式3。
题目摘自 :C++程序设计教程 第二版 作者 :钱能
思路出自 :《C++程序设计教程(第二版) 习题及解答 钱能 习题练习题答案》
另:教材非常好,整体内容结构分明,清晰易懂,
double StandardDeviation(QList<double> list ){
int n = list.count ();
double sigma = 0, pSigma = 0;
for (int i = 0; i < n; ++i) {
double v = list.at (i);
sigma += v; // sum
pSigma += v*v; // 平方和
}
sigma /= list.count (); // 获得平均值
return qSqrt( (pSigma/n - sigma*sigma)) ;
}
int main()
{
int arr[] = {6, 3, 7, 1, 4, 8, 2, 9, 11, 5};
// QList list ={6, 3, 7, 1, 4, 8, 2, 9, 11, 5};
QList<double> list(arr,arr+10);
double ret = StandardDeviation(list);
qDebug() << ret; // 3.03974
return 0;
}
网上有用 stl写法,前后使用了两次循环迭代
double sum = std::accumulate(std::begin(resultSet), std::end(resultSet), 0.0);
double mean = sum / resultSet.size(); //均值
double accum = 0.0;
std::for_each (std::begin(resultSet), std::end(resultSet), [&](const double d) {
accum += (d-mean)*(d-mean);
});
double stdev = sqrt(accum/(resultSet.size()-1)); //方差