Jai*_*ime 100
虽然平方和算法在大多数情况下都可以正常工作,但如果处理非常大的数字,它可能会造成很大的麻烦.你基本上可能会出现负差异......
另外,永远不要永远计算^ 2作为pow(a,2),a*a几乎肯定更快.
到目前为止,计算标准偏差的最佳方法是Welford的方法.我的C非常生疏,但它可能看起来像:
public static double StandardDeviation(List<double> valueList)
{
double M = 0.0;
double S = 0.0;
int k = 1;
foreach (double value in valueList)
{
double tmpM = M;
M += (value - tmpM) / k;
S += (value - tmpM) * (value - M);
k++;
}
return Math.Sqrt(S / (k-2));
}
Run Code Online (Sandbox Code Playgroud)
如果您拥有整个人口(而不是样本人口),那么请使用return Math.Sqrt(S / (k-1));.
编辑:我根据杰森的评论更新了代码......
编辑:我也根据Alex的评论更新了代码......
Jaime的解决方案比Jaime 快10倍,但请注意,Jaime指出:
"虽然平方和算法在大多数情况下都可以正常工作,但是如果处理非常大的数字会导致大麻烦.你基本上可能会出现负差异"
如果你认为你正在处理非常大的数字或非常大量的数字,你应该使用两种方法计算,如果结果相同,你肯定知道你可以使用"我的"方法.
public static double StandardDeviation(double[] data)
{
double stdDev = 0;
double sumAll = 0;
double sumAllQ = 0;
//Sum of x and sum of x²
for (int i = 0; i < data.Length; i++)
{
double x = data[i];
sumAll += x;
sumAllQ += x * x;
}
//Mean (not used here)
//double mean = 0;
//mean = sumAll / (double)data.Length;
//Standard deviation
stdDev = System.Math.Sqrt(
(sumAllQ -
(sumAll * sumAll) / data.Length) *
(1.0d / (data.Length - 1))
);
return stdDev;
}
Run Code Online (Sandbox Code Playgroud)
Jaime 接受的答案很好,除了你需要在最后一行除以 k-2(你需要除以“number_of_elements-1”)。更好的是,从 0 开始 k:
public static double StandardDeviation(List<double> valueList)
{
double M = 0.0;
double S = 0.0;
int k = 0;
foreach (double value in valueList)
{
k++;
double tmpM = M;
M += (value - tmpM) / k;
S += (value - tmpM) * (value - M);
}
return Math.Sqrt(S / (k-1));
}
Run Code Online (Sandbox Code Playgroud)
Math.NET 库为您提供了开箱即用的功能。
PM> 安装包 MathNet.Numerics
var populationStdDev = new List<double>(1d, 2d, 3d, 4d, 5d).PopulationStandardDeviation();
var sampleStdDev = new List<double>(2d, 3d, 4d).StandardDeviation();
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅人口标准偏差。