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;
}
}
}