3Sigma精度损失分析

问题背景

 apply反馈,review软件计算出来的3Sigma与excel计算出来的有些差距,总是差那么一点点。

问题现象

软件计算出来的标准差在后几位小数与excel表格使用STDEV函数计算出来的3Sigma不同,如:

表格导出的原始数据与利用STDEV函数计算的3Sigma

image

 

 

软件计算出来的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进行相应的操作即可。

posted @ 2026-04-28 09:54  盛沧海  阅读(18)  评论(0)    收藏  举报