3Sigma精度损失分析
问题背景
apply反馈,review软件计算出来的3Sigma与excel计算出来的有些差距,总是差那么一点点。
问题现象
软件计算出来的标准差在后几位小数与excel表格使用STDEV函数计算出来的3Sigma不同,如:
表格导出的原始数据与利用STDEV函数计算的3Sigma

软件计算出来的3Sigma为0.82848
也就是说保留5位小数后,使用函数计算的结果与软件计算结果总是有些微小差异。
排查过程
由于差异较小,怀疑应该是精度损失造成。
于是审查了3Sigma计算的方法,如下:
private double GetSigma3(IEnumerable<double> values) { if (values == null || values.Count() <1) throw new ArgumentException("Data array cannot be null or empty"); // 计算平均值 double mean = values.Average(); // 计算平方差之和 double sumOfSquares = values.Sum(x => Math.Pow(x - mean, 2)); // 计算方差(除以数据点总数N) double variance = sumOfSquares / values.Count(); // 返回标准差(方差的平方根) return Math.Round(Math.Sqrt(variance), 5) * 3; }
此处计算方差为使用 sumOfSquares / values.Count(),也就是说使用的是 平均差之和/n;
在求方差时若样本代表总体,那么在excel中是除以n来计算,;若使用的是总体中的样本,那么就需要使用除(n-1)来计算。
按Apply部门提供的标准差计算来看,他们使用的总体中的样本计算公式,也就是说计算方差时应该是 /(n-1) 才对;
然在将此处的修正后,方差在最后计算后还是与导出数据使用STDEV计算出的值相差一点点,再看代码时发现,
Round方法使用有问题,此处先Round再做乘以3,以求3Sigama,在使用Round时保留5位小数后,再乘以3,那么第5位小数后的相应数值乘以3的积就被人为省去了,必然造成异常。
原因分析
1. 需求分析不到位;此处就是软件使用的求标准差的方法与Apply使用的方法不一样所致。
2. 在计算时,先求约数,再做乘法;这是不允许的,这会导致省略后的相应数值的乘积被省略,若乘积有进位,就会导致最后求出的值变小。
解决方案
1. 修正方差统计算方法。
2. 修正3Sigma最后计算顺序,先乘再求约数。
全部修正后如下:
private double GetSigma3(IEnumerable<double> values) { if (values == null || values.Count() <= 1) throw new ArgumentException("Data array cannot be null or empty or only one data"); // 计算平均值 double mean = values.Average(); // 计算平方差之和 double sumOfSquares = values.Sum(x => Math.Pow(x - mean, 2)); // 计算方差(除以数据点总数N) double variance = sumOfSquares / (values.Count() - 1); // 返回标准差(方差的平方根) return Math.Round(Math.Sqrt(variance) * 3, 5);//修正精度损失 }
总结与建议
需求分析到位,如此处方差的计算方式要统一;
讲究工程操作,如此处先求约束再做运算来计算3Sigma是不允许的。
这里有一个问题,若无必要,尽量不要对浮点数做取舍,直接存储相应的数值是最好的,在UI上展示时,再使用格式化相应字符即可,如使用string中的format进行相应的操作即可。

浙公网安备 33010602011771号