using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Collections; using System.Data; using ASPNet_Drawing; /// ///SpcCaculator 的摘要说明 /// public class SpcCaculator { /// /// SPC系数表 ///(0)样本大小 (1)A (2)A2 (3)A3 (4)C4 (5)1/C4 (6)B3 (7)B4 (8)B5 (9)B6 (10)d2 (11)1/d2 (12)d3 (13)D1 (14)D2 (15)D3 (16)D4 (17)M3 (18)M3A2 /// static public double[,] SPC_coefficient = { {2,2.121,1.880,2.659,0.798,1.253,0,3.267,0,2.606,1.128,0.887,0.853,0,3.686,0,3.267,1.000,1.880}, {3,1.732,1.023,1.954,0.886,1.128,0,2.568,0,2.276,1.693,0.591,0.888,0,4.358,0,2.574,1.160,1.187}, {4,1.500,0.729,1.628,0.921,1.085,0,2.266,0,2.088,2.059,0.486,0.880,0,4.698,0,2.282,1.092,0.796}, {5,1.342,0.572,1.427,0.940,1.064,0,2.089,0,1.964,2.326,0.430,0.864,0,4.918,0,2.114,1.198,0.691}, {6,1.225,0.483,1.287,0.952,1.051,0.030,1.970,0.029,1.874,2.534,0.395,0.848,0,5.078,0,2.004,1.135,0.549}, {7,1.134,0.419,1.182,0.959,1.042,0.118,1.882,0.113,1.806,2.704,0.370,0.833,0.204,5.204,0.076,1.924,1.214,0.509}, {8,1.061,0.373,1.099,0.965,1.036,0.185,1.815,0.179,1.751,2.847,0.351,0.820,0.388,5.306,0.136,1.864,1.160,0.432}, {9,1.00,0.377,1.032,0.969,1.032,0.29,1.761,0.232,1.707,2.970,0.337,0.808,0.547,5.393,0.184,1.816,1.223,0.412}, {10,0.949,0.308,0.975,0.973,1.028,0.284,1.716,0.276,1.669,3.078,0.325,0.797,0.687,5.469,0.223,1.777,1.176,0.363}, {11,0.905,0.285,0.927,0.975,1.025,0.321,1.679,0.313,1.637,3.173,0.315,0.787,0.811,5.535,0.256,1.744,0,0}, {12,0.886,0.266,0.886,0.978,1.023,0.354,1.646,0.346,1.610,3.258,0.307,0.778,0.922,5.594,0.283,1.717,0,0}, {13,0.832,0.249,0.850,0.979,1.021,0.382,1.618,0.374,1.585,3.336,0.300,0.770,1.025,5.647,0.307,1.693,0,0}, {14,0.802,0.235,0.817,0.981,1.019,0.406,1.594,0.399,1.563,3.407,0.294,0.763,1.118,5.696,0.328,1.672,0,0}, {15,0.775,0.223,0.789,0.982,1.018,0.428,1.157,0.421,1.544,3.472,0.288,0.756,1.203,5.741,0.347,1.653,0,0}, {16,0.750,0.212,0.763,0.984,1.017,0.448,1.552,0.440,1.526,3.532,0.283,0.750,1.282,5.782,0.363,1.637,0,0}, {17,0.728,0.203,0.739,0.985,1.016,0.466,1.534,0.458,1.511,3.588,0.279,0.744,1.356,5.820,0.378,1.622,0,0}, {18,0.707,0.194,0.718,0.985,1.015,0.482,1.518,0.475,1.496,3.640,0.275,0.739,1.424,5.856,0.391,1.608,0,0}, {19,0.688,0.187,0.698,0.986,1.014,0.497,1.503,0.490,1.483,3.689,0.271,0.734,1.487,5.891,0.403,1.597,0,0}, {20,0.671,0.180,0.680,0.987,1.013,0.510,1.490,0.504,1.470,3.735,0.268,0.729,1.549,5.921,0.415,1.585,0,0}, {21,0.655,0.173,0.663,0.988,1.013,0.253,1.477,0.516,1.459,3.778,0.265,0.724,1.605,5.951,0.425,1.575,0,0}, {22,0.640,0.167,0.647,0.988,1.012,0.534,1.466,0.528,1.448,3.819,0.262,0.720,1.659,5.979,0.434,1.566,0,0}, {23,0.626,0.126,0.633,0.989,1.011,0.545,1.455,0.539,1.438,3.858,0.259,0.716,1.710,6.006,0.443,1.557,0,0}, {24,0.612,0.157,0.619,0989,1.011,0.555,1.445,0.549,1.429,3.895,0.257,0.712,1.759,6.031,0.451,1.548,0,0}, {25,0.600,0.153,0.606,0.990,1.011,0.565,1.435,0.559,1.420,3.931,0.254,0.708,1.806,6.056,0.459,1.541,0,0} }; static double QU_k = 0.99865; static double QL_k = 0.00135; /// /// 计算SPC主要参数: /// 输入:"X"被分析数据组;Usl理论上限;Lsl理论下限。 /// 输出:x平均值;"s"均方差;"QU"百分比上限;"QL"百分比下限;"cp"工序能力;"cpk"工序能力指数 /// /// 被分析数据组 /// 理论上限 /// 理论下限 /// 平均值 /// 均方差 /// 百分比上限 /// 百分比下限 /// 工序能力 /// 工序能力指数 public static void SpcValue(double[] X, ref double Usl, ref double Lsl, out double x, out double s, out double QU, out double QL, out double cp, out double cpk, out double[] sx, out double[] sy) { x = AVERAGE(X); s = STDEV(X); if (Usl == Lsl) { Usl = x + 4.0 * s; Lsl = x - 4.0 * s; } QU_QL(X, out QU, out QL); cp = Cp(QU, QL, Usl, Lsl); cpk = Cpk(x, QU, QL, Usl, Lsl); sxy(s, x, out sx, out sy); } /// /// 计算SPC主要参数: /// 输入:"X"被分析数据组;Usl理论上限;Lsl理论下限。 /// 输出:x平均值;"s"均方差;"QU"百分比上限;"QL"百分比下限;"cp"工序能力;"cpk"工序能力指数 /// /// 被分析数据组 /// 理论上限 /// 理论下限 /// 平均值 /// 均方差 /// 百分比上限 /// 百分比下限 /// 工序能力 /// 工序能力指数 public static void SpcValue(int n,double[] X, ref double Usl, ref double Lsl, out double x, out double s, out double QU, out double QL, out double cp, out double cpk, out double[] sx, out double[] sy) { x = AVERAGE(X); s = STDEV(X); if (Usl == Lsl) { Usl = x + 4.0 * s; Lsl = x - 4.0 * s; } QU_QL(X, out QU, out QL); cp = Cp(QU, QL, Usl, Lsl); cpk = Cpk(x, QU, QL, Usl, Lsl); sxy(s, x, out sx, out sy); double X2 = Spc_Data.Average(X, n); double S2 = Spc_Data.StandardDeviation_S2(X, n); double R2 = Spc_Data.Range_R2(X, n); double xiGamaC4; double xiGamaD2; double c4 = (double)Spc_Data.Spc_Param.Tables[Xml_Spc_Param.Table_Name].Rows[n - 2][Xml_Spc_Param.Param_C4]; double d2 = (double)Spc_Data.Spc_Param.Tables[Xml_Spc_Param.Table_Name].Rows[n - 2][Xml_Spc_Param.Param_L_D1]; xiGamaC4 = S2 / c4; xiGamaD2 = R2 / d2; double USL = Usl; double LSL = Lsl; double T = USL - LSL; double CP = T / (6 * xiGamaD2); double M = (USL + LSL) / 2.0; double M1 = M - X2; M1 = Math.Abs(M1); double CPK = CP - M1 / (3 * xiGamaD2); cp = CP; cpk = CPK; } /// /// 均方差 /// /// 被分析数据组 /// 均方差 public static double STDEV(double[] X) { if (X.Length < 2) return 0; double s = 0; //平均值 double x; x = AVERAGE(X); for (int i = 0; i < X.Length; i++) { s = s + (X[i] - x) * (X[i] - x); } s = Math.Sqrt(s / (double)(X.Length - 1)); return s; } /// /// 平均值 /// /// 被分析数据组 /// 平均值 public static double AVERAGE(double[] X) { return X.Average(); } /// /// 排序 /// /// /// public static double[] Sort(double[] X) { ArrayList temp = new ArrayList(X); temp.Sort(); return X = (double[])temp.ToArray(typeof(double)); } /// /// 已知表格行数为m,各行的数值分别记为 ,其中 表示第 行的数值, /// 将这 个数值由小到大排列,记排列后的数值为 ,其中 表示 个数值经排列之后第k个数值。 /// 给定上下标线数值0.99865和0.00135。计算Q上和Q下的方法为: ///a = (m - 1)* 0.99865 ///取a的整数部分为i,小数部分为j。 ///Q上 = (1 – j)* x(i+1)+ j * x(i+2) ///同理: ///b = (m - 1)* 0.00135 ///取b的整数部分为i,小数部分为j。 ///Q下 = (1 – j)* x(i+1)+ j * x(i+2) /// /// 被分析数据组 /// 百分比上限 /// 百分比下限 public static void QU_QL(double[] X, out double QU, out double QL) { QU = 0; QL = 0; double QU_n; int QU_n_i; double QU_n_j; double QL_n; int QL_n_i; double QL_n_j; X = Sort(X); QU_n = (double)(X.Length - 1) * QU_k; QU_n_i = (int)QU_n; QU_n_j = QU_n - QU_n_i; //Q上 = (1 – j)* x(i+1)+ j * x(i+2) QU = (1 - QU_n_j) * X[QU_n_i] + QU_n_j * X[QU_n_i + 1]; QL_n = (double)(X.Length - 1) * QL_k; QL_n_i = (int)QL_n; QL_n_j = QL_n - QL_n_i; //Q下 = (1 – j)* x(i+1)+ j * x(i+2) QL = (1 - QL_n_j) * X[QL_n_i] + QL_n_j * X[QL_n_i + 1]; return; } /// /// 工序能力 /// /// 被分析数据组 /// 理论上限 /// 理论下限 /// 工序能力 public static double Cp(double[] X, double Usl, double Lsl) { double QU; double QL; double cp = 0; QU_QL(X, out QU, out QL); cp = (Usl - Lsl) / (QU - QL); return cp; } /// /// 工序能力 /// /// 百分比上限 /// 百分比下限 /// 理论上限 /// 理论下限 /// public static double Cp(double QU, double QL, double Usl, double Lsl) { double cp = 0; cp = (Usl - Lsl) / (QU - QL); return cp; } /// /// 工序能力指数 /// /// 被分析数据组 /// 理论上限 /// 理论下限 /// public static double Cpk(double[] X, double Usl, double Lsl) { double cpk; double cpkU; double cpkL; double QU; double QL; double cp = 0; //均方差 double s; //均值 double x; x = AVERAGE(X); QU_QL(X, out QU, out QL); cp = (Usl - Lsl) / (QU - QL); cpkU = (Usl - x) / (QU - x); cpkL = (Lsl - x) / (QL - x); cpk = Math.Min(cpkU, cpkL); return cpk; } /// /// 工序能力指数 /// /// 平均值 /// 百分比上限 /// 百分比下限 /// 理论上限 /// 理论下限 /// public static double Cpk(double x, double QU, double QL, double Usl, double Lsl) { double cpk; double cpkU; double cpkL; double cp = 0; cp = Cp(QU, QL, Usl, Lsl); cpkU = (Usl - x) / (QU - x); cpkL = (x - Lsl) / (x - QL); cpk = Math.Min(cpkU, cpkL); return cpk; } /// /// 计算正态分布的x坐标,y坐标 /// /// 均方差 /// 平均值 public static void sxy(double s, double x, out double[] sx, out double[] sy) { double S2; double X2; X2 = x; S2 = s; sx = new double[11]; sy = new double[11]; double tempmaxdouble = 1.0 / (s * Math.Sqrt(2.0 * Math.PI)); sx[0] = X2 - 4.0 * S2; sx[1] = X2 - 3.0 * S2; sx[2] = X2 - 2.0 * S2; sx[3] = X2 - 1.0 * S2; sx[4] = X2 - 0.5 * S2; sx[5] = X2; sx[6] = X2 + 0.5 * S2; sx[7] = X2 + 1.0 * S2; sx[8] = X2 + 2.0 * S2; sx[9] = X2 + 3.0 * S2; sx[10] = X2 + 4.0 * S2; sy[0] = tempmaxdouble * Math.Exp(-16.0F / 2.0F); sy[1] = tempmaxdouble * Math.Exp(-9.0F / 2.0F); sy[2] = tempmaxdouble * Math.Exp(-4.0F / 2.0F); sy[3] = tempmaxdouble * Math.Exp(-1.0F / 2.0F); sy[4] = tempmaxdouble * Math.Exp(-0.25F / 2.0F); sy[5] = tempmaxdouble; sy[6] = tempmaxdouble * Math.Exp(-0.25F / 2.0F); sy[7] = tempmaxdouble * Math.Exp(-1.0F / 2.0F); sy[8] = tempmaxdouble * Math.Exp(-4.0F / 2.0F); sy[9] = tempmaxdouble * Math.Exp(-9.0F / 2.0F); sy[10] = tempmaxdouble * Math.Exp(-16.0F / 2.0F); double sy_sum = 0; for (int i = 0; i < sy.Length; i++) { sy_sum = sy_sum + sy[i]; } for (int i = 0; i < sy.Length; i++) { sy[i] = sy[i] / sy_sum; } } /// /// 根据查询的数据,获得理论上限,理论下限 /// /// /// 理论上限 /// 理论下限 public static void GetUslLsl(DataTable dt, out double Usl, out double Lsl) { Usl = 0; Lsl = 0; if (dt != null) { if (dt.Rows.Count > 0) { try { //Usl = Convert.ToDouble(dt.Rows[0]["上限值"]); //Lsl = Convert.ToDouble(dt.Rows[0]["下限值"]); Usl = 100; Lsl = 100; } catch { Usl = 0; Lsl = 0; } } } } } /// /// 测试数据 /// public class Spc_Data_TestData { /// /// 子组大小。单个子组观测值的个数 /// static public int n = 5; /// /// 子组个数 /// static public int k = 30; /// /// 特征值上限 /// static public double USL = 1.7; /// /// 特征值下限 /// static public double LSL = 1.5; /// /// 特征值上限 /// static public double USL1 = 1.0; /// /// 特征值下限 /// static public double LSL1 = 0.9; /// /// 特征值上限 /// static public double USL2 = 1.15; /// /// 特征值下限 /// static public double LSL2 = 1.10; /// /// 特征值上限 /// static public double USL3 = 129.01; /// /// 特征值下限 /// static public double LSL3 = 129; static public double[] X3 = { 129.006,129.006,129.006,129.005,129.006, 129.006,129.005,129.005,129.005,129.005, 129.005,129.006,129.007,129.006,129.005, 129.005,129.005,129.006,129.005,129.006, 129.006,129.006,129.007,129.006,129.005, 129.007,129.006,129.005,129.005,129.006, 129.006,129.007,129.005,129.005,129.005, 129.007,129.006,129.006,129.007,129.005, 129.007,129.005,129.005,129.006,129.007, 129.006,129.007,129.005,129.005,129.006 }; static public double[] X2 = { 1.141,1.130,1.131,1.127,1.137, 1.140,1.137,1.130,1.135,1.125, 1.133,1.133,1.131,1.128,1.127, 1.122,1.131,1.131,1.125,1.123, 1.131,1.128,1.117,1.133,1.136, 1.123,1.128,1.135,1.127,1.130, 1.138,1.126,1.130,1.133,1.133, 1.130,1.127,1.128,1.127,1.128, 1.122,1.142,1.128,1.135,1.133, 1.142,1.127,1.133,1.135,1.135 }; static public double[] X1 = { 0.941,0.942,0.947,0.939,0.942,0.943, 0.942,0.950,0.943,0.948,0.941,0.953, 0.944,0.943,0.941,0.933,0.942,0.941, 0.942,0.942,0.942,0.947,0.938,0.941, 0.947,0.943,0.943,0.948,0.938,0.946, 0.946,0.943,0.945,0.946,0.942,0.951, 0.951,0.938,0.938,0.952,0.947,0.945, 0.951,0.948,0.946,0.947,0.947,0.947, 0.953,0.956 }; static public double[] X = { 1.55,1.58,1.61,1.60,1.60,//1 1.58,1.63,1.63,1.62,1.63,//2 1.62,1.63,1.62,1.59,1.58,//3 1.58,1.60,1.61,1.62,1.63,//4 1.58,1.64,1.63,1.62,1.62,//5 1.62,1.62,1.63,1.61,1.57,//6 1.64,1.62,1.61,1.60,1.58,//7 1.57,1.59,1.61,1.62,1.63,//8 1.58,1.61,1.60,1.62,1.63,//9 1.60,1.61,1.64,1.64,1.63,//10 1.58,1.60,1.62,1.63,1.65,//11 1.62,1.58,1.59,1.57,1.58,//12 1.57,1.57,1.58,1.59,1.64,//13 1.61,1.64,1.62,1.60,1.59,//14 1.65,1.62,1.62,1.60,1.58,//15 1.57,1.59,1.57,1.59,1.62,//16 1.56,1.57,1.57,1.61,1.62,//17 1.56,1.58,1.59,1.60,1.62,//18 1.58,1.60,1.60,1.62,1.63,//19 1.58,1.59,1.60,1.63,1.62,//20 1.58,1.59,1.62,1.63,1.64,//21 1.58,1.59,1.62,1.63,1.61,//22 1.58,1.59,1.60,1.61,1.63,//23 1.57,1.59,1.61,1.61,1.62,//24 1.58,1.58,1.60,1.61,1.63,//25 1.62,1.58,1.58,1.58,1.57,//26 1.63,1.59,1.57,1.58,1.57,//27 1.58,1.62,1.61,1.63,1.61,//28 1.58,1.57,1.59,1.60,1.62,//29 1.62,1.60,1.60,1.57,1.57 //30 }; }