using System; using System.Collections.Generic; using System.Linq; namespace DAL { public static class CpCpkHelper { public static int SubGroup { get; set; } = 5; public static double d2 { get; set; } = 2.326; public static double D4 { get; set; } = 2.114; public static double A2 { get; set; } = 0.577; public static double D3 { get; set; } = 0; public static double B3 { get; set; } = 0; public static double B4 { get; set; } = 1.964; /// /// 获取List数组的平均值 /// /// list string 数组 /// 数组平均值 public static double GetAverage(List data) { List dataDouble = data.Select(double.Parse).ToList(); double sum = dataDouble.Sum(); double average = sum / dataDouble.Count; return average; } /// /// 获取标准差(此处是样本标准差 除以样本的个数-1) /// /// list string 数组 /// 数组标准差 public static double GetSigma(List data) { List dataDouble = data.Select(double.Parse).ToList(); double dAverage = dataDouble.Average(); double sumOfSquaredDifferences = dataDouble.Sum(x => Math.Pow(x - dAverage, 2)); double standardDeviation = Math.Sqrt(sumOfSquaredDifferences / (dataDouble.Count - 1)); return standardDeviation; } //计算R_(横线实际在上方)S_(子组极差平均值和子组标准差平均值) public static List GetR_S_(List data) { //丢弃最后无法满足子组内测量值个数的子组 int abandon = data.Count() % SubGroup; data.RemoveRange(data.Count() - abandon, abandon); List numericData = data.Select(double.Parse).ToList(); // 将数据转换为double类型 List R_List = new List(); List S_List = new List(); List R_S_List = new List(); //计算每个子组的极差和标准差 for (int i = 0; i <= numericData.Count() / SubGroup - 1; i++) { List group = numericData.GetRange(SubGroup * i, SubGroup); R_List.Add(group.Max() - group.Min()); S_List.Add(GetSigma(data.GetRange(SubGroup * i, SubGroup))); } R_S_List.Add(R_List.Average()); R_S_List.Add(S_List.Average()); return R_S_List; } /// /// 获取Cp相关数值 /// /// 测量数组 /// 测量上限值 /// 测量下限值 /// public static List GetCpList(List data, double USL, double LSL) { List R_S_ = GetR_S_(data); double sigma = R_S_[0] / d2; double Cp = (USL - LSL) / (6 * sigma); double average = GetAverage(data); double Cp_l = (USL - average) / (3 * sigma); double Cp_u = (average - LSL) / (3 * sigma); double Cp_k = Math.Min(Cp_l, Cp_u); return new List { Cp, Cp_l, Cp_u, Cp_k }; } /// /// 获取Pp相关数值 /// /// 测量数组 /// 测量上限值 /// 测量下限值 /// public static List GetPpList(List data, double USL, double LSL) { int abandon = data.Count() % SubGroup; data.RemoveRange(data.Count() - abandon, abandon); double s = GetSigma(data); double average = GetAverage(data); double Pp = (USL - LSL) / (6 * s); double Pp_u = (USL - average) / (3 * s); double Pp_l = (average - LSL) / (3 * s); double Pp_k = Math.Min(Pp_l, Pp_u); return new List { Pp, Pp_l, Pp_u, Pp_k }; } /// /// 计算CPCPK柱状图 /// /// /// public static Dictionary GetHistogramData(List data) { if (data.Count == 0) return new Dictionary(); // 计算合适的区间个数和区间宽度 var n_bins = (int)Math.Sqrt(data.Count()); var bin_width = (data.Max() - data.Min()) / n_bins; //计算每个区间的数量,存在List中 List countsList = new List(); for (int i = 0; i <= n_bins - 1; i++) { countsList.Add(0); } for (int i = 0; i <= data.Count() - 1; i++) { if (bin_width == 0) { countsList[0] = countsList[0] + 1; } else { int groupIndex = (int)Math.Floor((data[i] - data.Min()) / bin_width); if (groupIndex == n_bins) { groupIndex--; } countsList[groupIndex] = countsList[groupIndex] + 1; } } //计算范围 List rangeList = new List(); if (bin_width == 0) { string rangeStr = (data.Min()) + "-" + (data.Min()); rangeList.Add(rangeStr); } else { for (int i = 0; i <= n_bins - 1; i++) { string rangeStr = (i * bin_width + data.Min()) + "-" + ((i + 1) * bin_width + data.Min()); rangeList.Add(rangeStr); } } Dictionary result = new Dictionary(); if (bin_width == 0) { result.Add(rangeList[0], countsList[0].ToString()); } else { for (int i = 0; i <= n_bins - 1; i++) { result.Add(rangeList[i], countsList[i].ToString()); } } return result; } } }