Files

175 lines
5.2 KiB
C#

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;
/// <summary>
/// 获取List数组的平均值
/// </summary>
/// <param name="data">list string 数组</param>
/// <returns>数组平均值</returns>
public static double GetAverage(List<string> data)
{
List<double> dataDouble = data.Select(double.Parse).ToList();
double sum = dataDouble.Sum();
double average = sum / dataDouble.Count;
return average;
}
/// <summary>
/// 获取标准差(此处是样本标准差 除以样本的个数-1)
/// </summary>
/// <param name="data">list string 数组</param>
/// <returns>数组标准差</returns>
public static double GetSigma(List<string> data)
{
List<double> 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<double> GetR_S_(List<string> data)
{
//丢弃最后无法满足子组内测量值个数的子组
int abandon = data.Count() % SubGroup;
data.RemoveRange(data.Count() - abandon, abandon);
List<double> numericData = data.Select(double.Parse).ToList(); // 将数据转换为double类型
List<double> R_List = new List<double>();
List<double> S_List = new List<double>();
List<double> R_S_List = new List<double>();
//计算每个子组的极差和标准差
for (int i = 0; i <= numericData.Count() / SubGroup - 1; i++)
{
List<double> 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;
}
/// <summary>
/// 获取Cp相关数值
/// </summary>
/// <param name="data">测量数组</param>
/// <param name="USL">测量上限值</param>
/// <param name="LSL">测量下限值</param>
/// <returns></returns>
public static List<double> GetCpList(List<string> data, double USL, double LSL)
{
List<double> 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<double> { Cp, Cp_l, Cp_u, Cp_k };
}
/// <summary>
/// 获取Pp相关数值
/// </summary>
/// <param name="data">测量数组</param>
/// <param name="USL">测量上限值</param>
/// <param name="LSL">测量下限值</param>
/// <returns></returns>
public static List<double> GetPpList(List<string> 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<double> { Pp, Pp_l, Pp_u, Pp_k };
}
/// <summary>
/// 计算CPCPK柱状图
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public static Dictionary<string, string> GetHistogramData(List<double> data)
{
if (data.Count == 0) return new Dictionary<string, string>();
// 计算合适的区间个数和区间宽度
var n_bins = (int)Math.Sqrt(data.Count());
var bin_width = (data.Max() - data.Min()) / n_bins;
//计算每个区间的数量,存在List中
List<int> countsList = new List<int>();
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<string> rangeList = new List<string>();
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<string, string> result = new Dictionary<string, string>();
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;
}
}
}