#include "spc_core.h" // ==================== SPC 系数结构实现 ==================== SpcCoefficient::SpcCoefficient(int id, int num, double a, double a2, double a3, double b3, double b4, double b5, double b6, double d1, double d2, double d3, double d4, double c4, double c4_1, double l_d1, double l_d1_1) : ID(id), NUM(num), A(a), A2(a2), A3(a3), B3(b3), B4(b4), B5(b5), B6(b6), D1(d1), D2(d2), D3(d3), D4(d4), C4(c4), C4_1(c4_1), L_D1(l_d1), L_D1_1(l_d1_1) {} // ==================== SPC 系数表类实现 ==================== std::map SpcCoefficients::coefficientDict; void SpcCoefficients::Initialize() { static bool initialized = false; if (initialized) return; std::vector coefficients = { SpcCoefficient(1, 2, 2.121, 1.88, 2.659, 0, 3.267, 0, 2.606, 0, 3.686, 0, 3.267, 0.7979, 1.2533, 1.128, 0.8865), SpcCoefficient(2, 3, 1.732, 1.023, 1.954, 0, 2.568, 0, 2.676, 0, 4.358, 0, 2.574, 0.8862, 1.1284, 1.693, 0.5907), SpcCoefficient(3, 4, 1.5, 0.729, 1.628, 0, 2.266, 0, 2.088, 0, 4.698, 0, 2.282, 0.9213, 1.0854, 2.059, 0.4857), SpcCoefficient(4, 5, 1.342, 0.577, 1.427, 0, 2.089, 0, 1.964, 0, 4.918, 0, 2.114, 0.94, 1.0638, 2.326, 0.4299), SpcCoefficient(5, 6, 1.225, 0.483, 1.287, 0.03, 1.97, 0.029, 1.874, 0, 5.078, 0, 2.004, 0.9515, 1.051, 2.534, 0.3946), SpcCoefficient(6, 7, 1.134, 0.419, 1.182, 0.118, 1.882, 0.113, 1.806, 0.204, 5.204, 0.076, 1.924, 0.9594, 1.0423, 2.704, 0.3698), SpcCoefficient(7, 8, 1.061, 0.373, 1.099, 0.185, 1.815, 0.179, 1.751, 0.338, 5.306, 0.136, 1.864, 0.965, 1.0363, 2.847, 0.3512), SpcCoefficient(8, 9, 1, 0.337, 1.032, 0.239, 1.761, 0.232, 1.707, 0.547, 5.393, 0.184, 1.816, 0.9693, 1.0317, 2.97, 0.3367), SpcCoefficient(9, 10, 0.949, 0.308, 0.975, 0.284, 1.716, 2.276, 1.669, 0.687, 5.469, 0.223, 1.777, 0.9727, 1.0281, 3.078, 0.3249), SpcCoefficient(10, 11, 0.905, 0.285, 0.927, 0.321, 1.679, 0.313, 1.637, 0.811, 5.535, 0.256, 1.744, 0.9754, 1.0252, 3.173, 0.3152), SpcCoefficient(11, 12, 0.866, 0.266, 0.886, 0.354, 1.646, 0.346, 1.61, 0.922, 5.594, 0.283, 1.717, 0.9776, 1.0229, 3.258, 0.3069), SpcCoefficient(12, 13, 0.832, 0.249, 0.85, 0.382, 1.618, 0.374, 1.585, 1.025, 5.647, 0.307, 1.693, 0.9794, 1.021, 3.336, 0.2998), SpcCoefficient(13, 14, 0.802, 0.235, 0.817, 0.406, 1.594, 0.399, 1.563, 1.118, 5.696, 0.328, 1.672, 0.981, 1.0194, 3.407, 0.2935), SpcCoefficient(14, 15, 0.775, 0.223, 0.789, 0.428, 1.572, 0.421, 1.544, 1.203, 5.741, 0.347, 1.653, 0.9823, 1.018, 3.472, 0.288), SpcCoefficient(15, 16, 0.75, 0.212, 0.763, 0.448, 1.552, 0.44, 1.526, 1.282, 5.782, 0.363, 1.637, 0.9835, 1.0168, 3.532, 0.2831), SpcCoefficient(16, 17, 0.728, 0.203, 0.739, 0.466, 1.534, 0.458, 1.511, 1.356, 5.82, 0.378, 1.622, 0.9845, 1.0157, 3.588, 0.2787), SpcCoefficient(17, 18, 0.707, 0.194, 0.718, 0.482, 1.518, 0.475, 1.496, 1.424, 5.856, 0.391, 1.608, 0.9854, 1.0148, 3.64, 0.2747), SpcCoefficient(18, 19, 0.688, 0.187, 0.698, 0.497, 1.503, 0.49, 1.483, 1.487, 5.891, 0.403, 1.597, 0.9862, 1.014, 3.689, 0.2711), SpcCoefficient(19, 20, 0.671, 0.18, 0.68, 0.51, 1.49, 0.504, 1.47, 1.549, 5.921, 0.415, 1.585, 0.9869, 1.0133, 3.735, 0.2677), SpcCoefficient(20, 21, 0.655, 0.173, 0.663, 0.523, 1.477, 0.516, 1.459, 1.605, 5.951, 0.425, 1.575, 0.9876, 1.0126, 3.778, 0.2647), SpcCoefficient(21, 22, 0.64, 0.167, 0.647, 0.534, 1.466, 0.528, 1.448, 1.659, 5.979, 0.434, 1.566, 0.9882, 1.0119, 3.819, 0.2618), SpcCoefficient(22, 23, 0.626, 0.162, 0.633, 0.545, 1.455, 0.539, 1.438, 1.71, 6.006, 0.443, 1.557, 0.9887, 1.0114, 3.858, 0.2592), SpcCoefficient(23, 24, 0.612, 0.157, 0.619, 0.555, 1.445, 0.549, 1.429, 1.759, 6.031, 0.451, 1.548, 0.9892, 1.0109, 3.895, 0.2567), SpcCoefficient(24, 25, 0.6, 0.153, 0.606, 0.565, 1.435, 0.559, 1.42, 1.806, 6.056, 0.459, 1.541, 0.9896, 1.0105, 3.931, 0.2544)}; for (const auto &coeff : coefficients) { coefficientDict[coeff.NUM] = coeff; } initialized = true; } const SpcCoefficient &SpcCoefficients::GetBySubgroupSize(int subgroupSize) { Initialize(); auto it = coefficientDict.find(subgroupSize); if (it != coefficientDict.end()) { return it->second; } throw std::out_of_range("子组大小 " + std::to_string(subgroupSize) + " 不在有效范围 [2-25] 内"); } double SpcCoefficients::GetA2(int subgroupSize) { return GetBySubgroupSize(subgroupSize).A2; } double SpcCoefficients::GetA3(int subgroupSize) { return GetBySubgroupSize(subgroupSize).A3; } double SpcCoefficients::GetD3(int subgroupSize) { return GetBySubgroupSize(subgroupSize).D3; } double SpcCoefficients::GetD4(int subgroupSize) { return GetBySubgroupSize(subgroupSize).D4; } double SpcCoefficients::GetB3(int subgroupSize) { return GetBySubgroupSize(subgroupSize).B3; } double SpcCoefficients::GetB4(int subgroupSize) { return GetBySubgroupSize(subgroupSize).B4; } double SpcCoefficients::GetC4(int subgroupSize) { return GetBySubgroupSize(subgroupSize).C4; } double SpcCoefficients::GetL_D1(int subgroupSize) { return GetBySubgroupSize(subgroupSize).L_D1; } // ==================== 工具函数实现 ==================== double SpcUtils::Round(double value, int decimals) { double factor = std::pow(10.0, decimals); return std::round(value * factor) / factor; } double SpcUtils::Mean(const std::vector &values) { if (values.empty()) return 0.0; double sum = 0.0; for (double value : values) { sum += value; } return sum / values.size(); } double SpcUtils::Max(const std::vector &values) { if (values.empty()) return 0.0; double maxVal = values[0]; for (double value : values) { if (value > maxVal) maxVal = value; } return maxVal; } double SpcUtils::Min(const std::vector &values) { if (values.empty()) return 0.0; double minVal = values[0]; for (double value : values) { if (value < minVal) minVal = value; } return minVal; } double SpcUtils::Range(const std::vector &values) { if (values.size() < 2) return 0.0; return Max(values) - Min(values); } double SpcUtils::StandardDeviation(const std::vector &values) { if (values.size() < 2) return 0.0; double mean = Mean(values); double sumSquares = 0.0; for (double value : values) { double diff = value - mean; sumSquares += diff * diff; } return std::sqrt(sumSquares / (values.size() - 1)); } double SpcUtils::StandardDeviationPopulation(const std::vector &values) { if (values.size() < 2) return 0.0; double mean = Mean(values); double sumSquares = 0.0; for (double value : values) { double diff = value - mean; sumSquares += diff * diff; } return std::sqrt(sumSquares / values.size()); } std::string SpcUtils::GetCurrentTimestamp() { auto now = std::chrono::system_clock::now(); auto time = std::chrono::system_clock::to_time_t(now); std::tm tm; #ifdef _WIN32 localtime_s(&tm, &time); #else localtime_r(&time, &tm); #endif std::ostringstream oss; oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S"); return oss.str(); } // ==================== SPC 数据类实现 ==================== SpcDataXR::SpcDataXR() : n(0), k(0), CL_X(0.0), UCL_X(0.0), LCL_X(0.0), CL_R(0.0), UCL_R(0.0), LCL_R(0.0) {} json SpcDataXR::ToJson() const { json j; j["n"] = n; j["k"] = k; j["CL_X"] = CL_X; j["UCL_X"] = UCL_X; j["LCL_X"] = LCL_X; j["CL_R"] = CL_R; j["UCL_R"] = UCL_R; j["LCL_R"] = LCL_R; j["CL_Xk"] = CL_Xk; j["CL_Rk"] = CL_Rk; return j; } SpcDataXR SpcDataXR::FromJson(const json &j) { SpcDataXR data; data.n = j.value("n", 0); data.k = j.value("k", 0); data.CL_X = j.value("CL_X", 0.0); data.UCL_X = j.value("UCL_X", 0.0); data.LCL_X = j.value("LCL_X", 0.0); data.CL_R = j.value("CL_R", 0.0); data.UCL_R = j.value("UCL_R", 0.0); data.LCL_R = j.value("LCL_R", 0.0); if (j.contains("CL_Xk")) { data.CL_Xk = j["CL_Xk"].get>(); } if (j.contains("CL_Rk")) { data.CL_Rk = j["CL_Rk"].get>(); } return data; } SpcDataXS::SpcDataXS() : n(0), k(0), CL_X(0.0), UCL_X(0.0), LCL_X(0.0), CL_S(0.0), UCL_S(0.0), LCL_S(0.0) {} json SpcDataXS::ToJson() const { json j; j["n"] = n; j["k"] = k; j["CL_X"] = CL_X; j["UCL_X"] = UCL_X; j["LCL_X"] = LCL_X; j["CL_S"] = CL_S; j["UCL_S"] = UCL_S; j["LCL_S"] = LCL_S; j["CL_Xk"] = CL_Xk; j["CL_Sk"] = CL_Sk; return j; } SpcDataXS SpcDataXS::FromJson(const json &j) { SpcDataXS data; data.n = j.value("n", 0); data.k = j.value("k", 0); data.CL_X = j.value("CL_X", 0.0); data.UCL_X = j.value("UCL_X", 0.0); data.LCL_X = j.value("LCL_X", 0.0); data.CL_S = j.value("CL_S", 0.0); data.UCL_S = j.value("UCL_S", 0.0); data.LCL_S = j.value("LCL_S", 0.0); if (j.contains("CL_Xk")) { data.CL_Xk = j["CL_Xk"].get>(); } if (j.contains("CL_Sk")) { data.CL_Sk = j["CL_Sk"].get>(); } return data; } SpcDataCpk::SpcDataCpk() : n(0), k(0), SL(0.0), USL(0.0), LSL(0.0), Singma(0.0), SingmaS(0.0), Ca(0.0), Cp(0.0), CPU(0.0), CPL(0.0), CR(0.0), Cpk(0.0), Pp(0.0), PPU(0.0), PPL(0.0), PR(0.0), Ppk(0.0), ProcessSpread(0.0), GroupWidth(0.0), GroupCount(0), ValueMax(0.0), ValueMin(0.0) {} json SpcDataCpk::ToJson() const { json j; j["n"] = n; j["k"] = k; j["SL"] = SL; j["USL"] = USL; j["LSL"] = LSL; j["Singma"] = Singma; j["SingmaS"] = SingmaS; j["Ca"] = Ca; j["Cp"] = Cp; j["CPU"] = CPU; j["CPL"] = CPL; j["CR"] = CR; j["Cpk"] = Cpk; j["Pp"] = Pp; j["PPU"] = PPU; j["PPL"] = PPL; j["PR"] = PR; j["Ppk"] = Ppk; j["ProcessSpread"] = ProcessSpread; j["GroupWidth"] = GroupWidth; j["GroupCount"] = GroupCount; j["ValueMax"] = ValueMax; j["ValueMin"] = ValueMin; j["Xk"] = Xk; j["XkUp"] = XkUp; j["XkDown"] = XkDown; j["Yk"] = Yk; j["YkCount"] = YkCount; j["NormalDistributionX"] = NormalDistributionX; j["NormalDistributionY"] = NormalDistributionY; return j; } SpcDataCpk SpcDataCpk::FromJson(const json &j) { SpcDataCpk data; data.n = j.value("n", 0); data.k = j.value("k", 0); data.SL = j.value("SL", 0.0); data.USL = j.value("USL", 0.0); data.LSL = j.value("LSL", 0.0); data.Singma = j.value("Singma", 0.0); data.SingmaS = j.value("SingmaS", 0.0); data.Ca = j.value("Ca", 0.0); data.Cp = j.value("Cp", 0.0); data.CPU = j.value("CPU", 0.0); data.CPL = j.value("CPL", 0.0); data.CR = j.value("CR", 0.0); data.Cpk = j.value("Cpk", 0.0); data.Pp = j.value("Pp", 0.0); data.PPU = j.value("PPU", 0.0); data.PPL = j.value("PPL", 0.0); data.PR = j.value("PR", 0.0); data.Ppk = j.value("Ppk", 0.0); data.ProcessSpread = j.value("ProcessSpread", 0.0); data.GroupWidth = j.value("GroupWidth", 0.0); data.GroupCount = j.value("GroupCount", 0); data.ValueMax = j.value("ValueMax", 0.0); data.ValueMin = j.value("ValueMin", 0.0); if (j.contains("Xk")) { data.Xk = j["Xk"].get>(); } if (j.contains("XkUp")) { data.XkUp = j["XkUp"].get>(); } if (j.contains("XkDown")) { data.XkDown = j["XkDown"].get>(); } if (j.contains("Yk")) { data.Yk = j["Yk"].get>(); } if (j.contains("YkCount")) { data.YkCount = j["YkCount"].get>(); } if (j.contains("NormalDistributionX")) { data.NormalDistributionX = j["NormalDistributionX"].get>(); } if (j.contains("NormalDistributionY")) { data.NormalDistributionY = j["NormalDistributionY"].get>(); } return data; } // ==================== 统一的 SPC 计算结果 JSON 结构实现 ==================== SpcResultJson::SpcResultJson() : Timestamp(SpcUtils::GetCurrentTimestamp()), Version("1.0") {} json SpcResultJson::ToJson() const { json j; j["XR"] = XR.ToJson(); j["XS"] = XS.ToJson(); j["Cpk"] = Cpk.ToJson(); j["Timestamp"] = Timestamp; j["Version"] = Version; return j; } SpcResultJson SpcResultJson::FromJson(const json &j) { SpcResultJson result; if (j.contains("XR")) { result.XR = SpcDataXR::FromJson(j["XR"]); } if (j.contains("XS")) { result.XS = SpcDataXS::FromJson(j["XS"]); } if (j.contains("Cpk")) { result.Cpk = SpcDataCpk::FromJson(j["Cpk"]); } result.Timestamp = j.value("Timestamp", SpcUtils::GetCurrentTimestamp()); result.Version = j.value("Version", "1.0"); return result; } // ==================== SPC 计算器实现 ==================== void SpcCalculator::CalculateHistogramData(const std::vector &data, SpcDataCpk &result) { result.Xk.resize(result.GroupCount); result.XkDown.resize(result.GroupCount); result.XkUp.resize(result.GroupCount); result.Yk.resize(result.GroupCount); result.YkCount.resize(result.GroupCount, 0.0); // 计算组边界 for (int i = 0; i < result.GroupCount; i++) { if (i == 0) { result.XkDown[0] = result.ValueMin; result.XkUp[0] = result.ValueMin + result.GroupWidth; } else { result.XkDown[i] = result.XkDown[i - 1] + result.GroupWidth; result.XkUp[i] = result.XkUp[i - 1] + result.GroupWidth; } result.Xk[i] = (result.XkDown[i] + result.XkUp[i]) / 2.0; } // 最后一组的上边界调整,确保包含最大值 result.XkUp[result.GroupCount - 1] = result.ValueMax; // 统计频数 for (double value : data) { for (int i = 0; i < result.GroupCount; i++) { if (value >= result.XkDown[i] && (i == result.GroupCount - 1 ? value <= result.XkUp[i] : value < result.XkUp[i])) { result.YkCount[i]++; break; } } } // 计算频率百分比 for (int i = 0; i < result.GroupCount; i++) { result.Yk[i] = result.YkCount[i] / data.size() * 100.0; } } void SpcCalculator::CalculateNormalDistributionCurve(double mean, double sigma, SpcDataCpk &result) { result.NormalDistributionX.resize(9); result.NormalDistributionY.resize(9); // X坐标:-3σ到+3σ for (int i = 0; i < 9; i++) { double sigmaMultiple = (i - 4) * 0.5; result.NormalDistributionX[i] = mean + sigmaMultiple * sigma; } // 计算最大频数用于缩放 double maxCount = result.YkCount.empty() ? 1.0 : *std::max_element(result.YkCount.begin(), result.YkCount.end()); // Y坐标:正态分布概率密度(按最大频数缩放) for (int i = 0; i < 9; i++) { double x = result.NormalDistributionX[i]; double exponent = -0.5 * std::pow((x - mean) / sigma, 2); result.NormalDistributionY[i] = maxCount * std::exp(exponent); } } SpcDataXR SpcCalculator::CalculateXR(const std::vector &data, int subgroupSize) { SpcDataXR result; if (data.empty() || subgroupSize < MIN_SUBGROUP_SIZE) { return result; } int k = data.size() / subgroupSize; if (k == 0) return result; result.n = subgroupSize; result.k = k; // 获取 SPC 系数 const SpcCoefficient &coeff = SpcCoefficients::GetBySubgroupSize(subgroupSize); // 计算各子组平均值和极差 result.CL_Xk.resize(k); result.CL_Rk.resize(k); for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); result.CL_Xk[i] = SpcUtils::Mean(subgroup); result.CL_Rk[i] = SpcUtils::Range(subgroup); } // 计算中心线 result.CL_X = SpcUtils::Mean(result.CL_Xk); result.CL_R = SpcUtils::Mean(result.CL_Rk); // 计算控制限 result.UCL_X = result.CL_X + coeff.A2 * result.CL_R; result.LCL_X = result.CL_X - coeff.A2 * result.CL_R; result.UCL_R = coeff.D4 * result.CL_R; result.LCL_R = coeff.D3 * result.CL_R; return result; } SpcDataXS SpcCalculator::CalculateXS(const std::vector &data, int subgroupSize) { SpcDataXS result; if (data.empty() || subgroupSize < MIN_SUBGROUP_SIZE) { return result; } int k = data.size() / subgroupSize; if (k == 0) return result; result.n = subgroupSize; result.k = k; // 获取 SPC 系数 const SpcCoefficient &coeff = SpcCoefficients::GetBySubgroupSize(subgroupSize); // 计算各子组平均值和标准差 result.CL_Xk.resize(k); result.CL_Sk.resize(k); for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); result.CL_Xk[i] = SpcUtils::Mean(subgroup); result.CL_Sk[i] = SpcUtils::StandardDeviation(subgroup); // 样本标准差 } // 计算中心线 result.CL_X = SpcUtils::Mean(result.CL_Xk); result.CL_S = SpcUtils::Mean(result.CL_Sk); // 使用极差计算控制限(与原始代码一致) double rBar = 0.0; for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); rBar += SpcUtils::Range(subgroup); } rBar /= k; // 计算控制限 result.UCL_X = result.CL_X + coeff.A3 * rBar; result.LCL_X = result.CL_X - coeff.A3 * rBar; result.UCL_S = coeff.B4 * result.CL_S; result.LCL_S = coeff.B3 * result.CL_S; return result; } SpcDataCpk SpcCalculator::CalculateCpk(const std::vector &data, int subgroupSize, double usl, double lsl) { SpcDataCpk result; if (data.empty() || subgroupSize < MIN_SUBGROUP_SIZE) { return result; } int k = data.size() / subgroupSize; if (k == 0) return result; result.n = subgroupSize; result.k = k; result.USL = usl; result.LSL = lsl; // 如果没给出规格限,使用3σ限 if (std::abs(usl - lsl) < 0.000001) { double overallMean1 = SpcUtils::Mean(data); double overallStd = SpcUtils::StandardDeviationPopulation(data); usl = overallMean1 + 3 * overallStd; lsl = overallMean1 - 3 * overallStd; result.USL = usl; result.LSL = lsl; } // 计算总体平均值 double overallMean = SpcUtils::Mean(data); // 获取 SPC 系数 const SpcCoefficient &coeff = SpcCoefficients::GetBySubgroupSize(subgroupSize); // 计算组内标准差估计值(使用R-bar/d2) double rBar = 0.0; for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); rBar += SpcUtils::Range(subgroup); } rBar /= k; result.Singma = rBar / coeff.L_D1; // 组内标准差 // 计算标准差平均值 double sBar = 0.0; for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); sBar += SpcUtils::StandardDeviation(subgroup); } sBar /= k; result.SingmaS = sBar; // 计算能力指数 double tolerance = usl - lsl; if (tolerance > 0) { result.Cp = tolerance / (6 * result.Singma); result.CPU = (usl - overallMean) / (3 * result.Singma); result.CPL = (overallMean - lsl) / (3 * result.Singma); result.Cpk = std::min(result.CPU, result.CPL); result.Pp = tolerance / (6 * result.SingmaS); result.PPU = (usl - overallMean) / (3 * result.SingmaS); result.PPL = (overallMean - lsl) / (3 * result.SingmaS); result.Ppk = std::min(result.PPU, result.PPL); // 计算 Ca(过程准确度) double center = (usl + lsl) / 2.0; result.Ca = std::abs(overallMean - center) / (tolerance / 2.0); // 计算 CR 和 PR result.CR = 6 * result.Singma / tolerance; result.PR = 6 * result.SingmaS / tolerance; result.SL = center; } // 计算直方图数据 result.ValueMax = SpcUtils::Max(data); result.ValueMin = SpcUtils::Min(data); result.ProcessSpread = result.ValueMax - result.ValueMin; // 分组数(Sturges公式) result.GroupCount = 1 + static_cast(3.32 * std::log10(data.size())); result.GroupWidth = result.ProcessSpread / result.GroupCount; // 计算分组数据 CalculateHistogramData(data, result); // 计算正态分布曲线 CalculateNormalDistributionCurve(overallMean, result.SingmaS, result); return result; } json SpcCalculator::Spc(const json ¶m) { try { SpcTestData req_param = SpcTestData::FromJson(param); // 使用测试数据 const std::vector &testData = req_param.x; // 改为小写 x int subgroupSize = req_param.n; double usl = req_param.usl; double lsl = req_param.lsl; // 计算并获取整合的 JSON SpcDataXR xr = CalculateXR(testData, subgroupSize); SpcDataXS xs = CalculateXS(testData, subgroupSize); SpcDataCpk cpk = CalculateCpk(testData, subgroupSize, usl, lsl); // 四舍五入所有数值 RoundSpcData(xr, xs, cpk); SpcResultJson result; result.XR = xr; result.XS = xs; result.Cpk = cpk; return result.ToJson(); } catch (const std::exception &e) { json error; error["error"] = "SPC calculation failed: " + std::string(e.what()); return error; } } json SpcCalculator::CalculateAllToJson(const std::vector &data, int subgroupSize, double usl, double lsl) { SpcDataXR xr = CalculateXR(data, subgroupSize); SpcDataXS xs = CalculateXS(data, subgroupSize); SpcDataCpk cpk = CalculateCpk(data, subgroupSize, usl, lsl); // 四舍五入所有数值 RoundSpcData(xr, xs, cpk); SpcResultJson result; result.XR = xr; result.XS = xs; result.Cpk = cpk; return result.ToJson(); // 缩进2个空格 // return result.ToJson().dump(2); // 缩进2个空格 } void SpcCalculator::RoundSpcData(SpcDataXR &xr, SpcDataXS &xs, SpcDataCpk &cpk, int decimals) { RoundSpcDataXR(xr, decimals); RoundSpcDataXS(xs, decimals); RoundSpcDataCpk(cpk, decimals); } void SpcCalculator::RoundSpcDataXR(SpcDataXR &data, int decimals) { data.CL_X = SpcUtils::Round(data.CL_X, decimals); data.UCL_X = SpcUtils::Round(data.UCL_X, decimals); data.LCL_X = SpcUtils::Round(data.LCL_X, decimals); data.CL_R = SpcUtils::Round(data.CL_R, decimals); data.UCL_R = SpcUtils::Round(data.UCL_R, decimals); data.LCL_R = SpcUtils::Round(data.LCL_R, decimals); for (double &value : data.CL_Xk) { value = SpcUtils::Round(value, decimals); } for (double &value : data.CL_Rk) { value = SpcUtils::Round(value, decimals); } } void SpcCalculator::RoundSpcDataXS(SpcDataXS &data, int decimals) { data.CL_X = SpcUtils::Round(data.CL_X, decimals); data.UCL_X = SpcUtils::Round(data.UCL_X, decimals); data.LCL_X = SpcUtils::Round(data.LCL_X, decimals); data.CL_S = SpcUtils::Round(data.CL_S, decimals); data.UCL_S = SpcUtils::Round(data.UCL_S, decimals); data.LCL_S = SpcUtils::Round(data.LCL_S, decimals); for (double &value : data.CL_Xk) { value = SpcUtils::Round(value, decimals); } for (double &value : data.CL_Sk) { value = SpcUtils::Round(value, decimals); } } void SpcCalculator::RoundSpcDataCpk(SpcDataCpk &data, int decimals) { data.SL = SpcUtils::Round(data.SL, decimals); data.USL = SpcUtils::Round(data.USL, decimals); data.LSL = SpcUtils::Round(data.LSL, decimals); data.Singma = SpcUtils::Round(data.Singma, decimals); data.SingmaS = SpcUtils::Round(data.SingmaS, decimals); data.Ca = SpcUtils::Round(data.Ca, decimals); data.Cp = SpcUtils::Round(data.Cp, decimals); data.CPU = SpcUtils::Round(data.CPU, decimals); data.CPL = SpcUtils::Round(data.CPL, decimals); data.CR = SpcUtils::Round(data.CR, decimals); data.Cpk = SpcUtils::Round(data.Cpk, decimals); data.Pp = SpcUtils::Round(data.Pp, decimals); data.PPU = SpcUtils::Round(data.PPU, decimals); data.PPL = SpcUtils::Round(data.PPL, decimals); data.PR = SpcUtils::Round(data.PR, decimals); data.Ppk = SpcUtils::Round(data.Ppk, decimals); data.ProcessSpread = SpcUtils::Round(data.ProcessSpread, decimals); data.GroupWidth = SpcUtils::Round(data.GroupWidth, decimals); data.ValueMax = SpcUtils::Round(data.ValueMax, decimals); data.ValueMin = SpcUtils::Round(data.ValueMin, decimals); for (double &value : data.Xk) value = SpcUtils::Round(value, decimals); for (double &value : data.XkUp) value = SpcUtils::Round(value, decimals); for (double &value : data.XkDown) value = SpcUtils::Round(value, decimals); for (double &value : data.Yk) value = SpcUtils::Round(value, decimals); for (double &value : data.YkCount) value = SpcUtils::Round(value, decimals); for (double &value : data.NormalDistributionX) value = SpcUtils::Round(value, decimals); for (double &value : data.NormalDistributionY) value = SpcUtils::Round(value, decimals); } double SpcCalculator::CalculateCp(const std::vector &data, int subgroupSize, double usl, double lsl) { const SpcCoefficient &coeff = SpcCoefficients::GetBySubgroupSize(subgroupSize); int k = data.size() / subgroupSize; double rBar = 0.0; for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); rBar += SpcUtils::Range(subgroup); } rBar /= k; double sigma = rBar / coeff.L_D1; return (usl - lsl) / (6 * sigma); } double SpcCalculator::CalculatePp(const std::vector &data, int subgroupSize, double usl, double lsl) { double sigma = SpcUtils::StandardDeviationPopulation(data); return (usl - lsl) / (6 * sigma); } double SpcCalculator::CalculateCpu(const std::vector &data, int subgroupSize, double usl) { const SpcCoefficient &coeff = SpcCoefficients::GetBySubgroupSize(subgroupSize); double overallMean = SpcUtils::Mean(data); int k = data.size() / subgroupSize; double rBar = 0.0; for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); rBar += SpcUtils::Range(subgroup); } rBar /= k; double sigma = rBar / coeff.L_D1; return (usl - overallMean) / (3 * sigma); } double SpcCalculator::CalculateCpl(const std::vector &data, int subgroupSize, double lsl) { const SpcCoefficient &coeff = SpcCoefficients::GetBySubgroupSize(subgroupSize); double overallMean = SpcUtils::Mean(data); int k = data.size() / subgroupSize; double rBar = 0.0; for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); rBar += SpcUtils::Range(subgroup); } rBar /= k; double sigma = rBar / coeff.L_D1; return (overallMean - lsl) / (3 * sigma); } double SpcCalculator::CalculateXbarbar(const std::vector &data, int subgroupSize) { int k = data.size() / subgroupSize; std::vector subgroupMeans(k); for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); subgroupMeans[i] = SpcUtils::Mean(subgroup); } return SpcUtils::Mean(subgroupMeans); } double SpcCalculator::CalculateRbar(const std::vector &data, int subgroupSize) { int k = data.size() / subgroupSize; std::vector subgroupRanges(k); for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); subgroupRanges[i] = SpcUtils::Range(subgroup); } return SpcUtils::Mean(subgroupRanges); } double SpcCalculator::CalculateSbar(const std::vector &data, int subgroupSize) { int k = data.size() / subgroupSize; std::vector subgroupStdDevs(k); for (int i = 0; i < k; i++) { std::vector subgroup(subgroupSize); std::copy(data.begin() + i * subgroupSize, data.begin() + (i + 1) * subgroupSize, subgroup.begin()); subgroupStdDevs[i] = SpcUtils::StandardDeviation(subgroup); } return SpcUtils::Mean(subgroupStdDevs); } // ==================== 直方图计算器实现 ==================== void HistogramCalculator::CalculateHistogram(const std::vector &data, int numBins, std::vector &frequencies, std::vector &cumulativePercentages) { frequencies.clear(); cumulativePercentages.clear(); if (data.empty() || numBins <= 0) return; frequencies.resize(numBins, 0); cumulativePercentages.resize(numBins, 0.0); double min = SpcUtils::Min(data); double max = SpcUtils::Max(data); double binWidth = (max - min) / numBins; // 调整边界,确保所有数据都能被包含 min = std::floor(min / binWidth) * binWidth; max = std::ceil(max / binWidth) * binWidth; binWidth = (max - min) / numBins; // 统计频数 for (double value : data) { int binIndex = static_cast(std::floor((value - min) / binWidth)); if (binIndex == numBins) binIndex--; // 处理最大值的情况 frequencies[binIndex]++; } // 计算累计百分比 int total = data.size(); int cumulative = 0; for (int i = 0; i < numBins; i++) { cumulative += frequencies[i]; cumulativePercentages[i] = static_cast(cumulative) / total * 100.0; } } double HistogramCalculator::CalculateBinWidth(const std::vector &data, int numBins) { if (data.size() < 2 || numBins <= 0) return 0.0; double min = SpcUtils::Min(data); double max = SpcUtils::Max(data); double binWidth = (max - min) / numBins; // 舍入组距的内部函数 auto RoundInterval = [](double interval) -> double { if (interval == 0.0) { throw std::out_of_range("组距不能为零"); } // 处理大于1的情况 double step = -1.0; double tempValue = interval; while (tempValue > 1.0) { step++; tempValue = tempValue / 10.0; if (step > 1000) { throw std::runtime_error("自动组距计算错误"); } } // 处理小于1的情况 tempValue = interval; if (tempValue < 1.0) { step = 0.0; } while (tempValue < 1.0) { step--; tempValue = tempValue * 10.0; if (step < -1000) { throw std::runtime_error("自动组距计算错误"); } } double tempDiff = interval / std::pow(10.0, step); if (tempDiff < 3.0) { tempDiff = 2.0; } else if (tempDiff < 7.0) { tempDiff = 5.0; } else { tempDiff = 10.0; } return tempDiff * std::pow(10.0, step); }; return RoundInterval(binWidth); } // ==================== API 响应和请求类实现 ==================== SpcTestData::SpcTestData() : n(0), k(0), usl(0.0), lsl(0.0) {} json SpcTestData::ToJson() const { json j; j["n"] = n; j["k"] = k; j["usl"] = usl; j["lsl"] = lsl; j["x"] = x; return j; } SpcTestData SpcTestData::FromJson(const json &j) { SpcTestData data; data.n = j.value("n", 0); data.k = j.value("k", 0); data.usl = j.value("usl", 0.0); data.lsl = j.value("lsl", 0.0); if (j.contains("x")) { data.x = j["x"].get>(); } return data; } // ApiResponseSpc::ApiResponseSpc() : success(false), code(0) {} // json ApiResponseSpc::ToJson() const // { // json j; // j["success"] = success; // j["code"] = code; // j["msg"] = msg; // j["req_code"] = req_code; // j["req_from"] = req_from; // j["req_cmd"] = req_cmd; // if (req_param) // { // j["req_param"] = req_param->ToJson(); // } // return j; // } // ApiResponseSpc ApiResponseSpc::FromJson(const json &j) // { // ApiResponseSpc response; // response.success = j.value("success", false); // response.code = j.value("code", 0); // response.msg = j.value("msg", ""); // response.req_code = j.value("req_code", ""); // response.req_from = j.value("req_from", ""); // response.req_cmd = j.value("req_cmd", ""); // if (j.contains("req_param")) // { // response.req_param = std::make_shared(); // *response.req_param = SpcRequestParam::FromJson(j["req_param"]); // } // return response; // } // ==================== SPC 数据处理工具实现 ==================== // ApiResponseSpc SpcDataProcessor::DeserializeApiResponseSpc(const std::string &jsonStr) // { // ApiResponseSpc response; // response.success = true; // if (jsonStr.empty()) // { // response.success = false; // response.msg = "JSON 字符串不能为空"; // return response; // } // try // { // json j = json::parse(jsonStr); // response = ApiResponseSpc::FromJson(j); // // 验证响应 // ApiResponseSpc validationResult = ValidateResponse(response); // response.success = validationResult.success; // response.msg = validationResult.msg; // return response; // } // catch (const std::exception &ex) // { // response.success = false; // response.msg = "JSON 字符串符不合理: " + std::string(ex.what()); // return response; // } // } // SpcTestData SpcDataProcessor::ExtractSpcTestData(const ApiResponseSpc &response) // { // if (!response.success || !response.req_param) // { // return SpcTestData(); // } // SpcTestData data; // data.n = response.req_param->n; // data.k = response.req_param->k; // data.usl = response.req_param->usl; // data.lsl = response.req_param->lsl; // data.x = response.req_param->x; // return data; // } // ApiResponseSpc SpcDataProcessor::ValidateResponse(const ApiResponseSpc &response) // { // ApiResponseSpc result; // result.success = true; // if (!response.req_param) // { // result.success = false; // result.msg = "请求参数为空"; // return result; // } // const auto &data = *response.req_param; // // 验证 SPC 数据完整性 // if (data.n <= 0) // { // result.success = false; // result.msg = "n=" + std::to_string(data.n) + "子组大小必须大于0"; // return result; // } // if (data.k <= 0) // { // result.success = false; // result.msg = "k=" + std::to_string(data.k) + "子组个数必须大于0"; // return result; // } // if (data.x.empty()) // { // result.success = false; // result.msg = "测量数据不能为空"; // return result; // } // // 验证数据个数是否匹配 // int expectedDataCount = data.n * data.k; // if (data.x.size() != expectedDataCount) // { // result.success = false; // result.msg = "数据个数不匹配:子组大小(n)=" + std::to_string(data.n) + // ", 子组个数(k)=" + std::to_string(data.k) + // ", 期望数据个数=" + std::to_string(expectedDataCount) + // ", 实际数据个数=" + std::to_string(data.x.size()); // return result; // } // if (data.usl <= data.lsl) // { // result.success = true; // result.msg = "警告: 规格上限应大于规格下限,SPC 数据完整"; // return result; // } // result.success = true; // result.msg = "SPC 数据完整"; // return result; // } // ==================== 示例数据实现 ==================== namespace Spc_Data_TestData { const int n = 5; const int k = 30; const double USL = 1.7; const double LSL = 1.5; const std::vector 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 }; } // ==================== 示例函数实现 ==================== void RunJsonExample_5_30() { std::cout << "=== SPC JSON 计算示例 (n=5, k=30) ===" << std::endl; // 使用测试数据 const std::vector &testData = Spc_Data_TestData::X; int subgroupSize = Spc_Data_TestData::n; double usl = Spc_Data_TestData::USL; double lsl = Spc_Data_TestData::LSL; // 计算并获取整合的 JSON std::string jsonResult = SpcCalculator::CalculateAllToJson(testData, subgroupSize, usl, lsl); std::cout << "整合的 SPC JSON 结果:" << std::endl; std::cout << jsonResult << std::endl; // 也可以单独计算 SpcDataXR xr = SpcCalculator::CalculateXR(testData, subgroupSize); SpcDataXS xs = SpcCalculator::CalculateXS(testData, subgroupSize); SpcDataCpk cpk = SpcCalculator::CalculateCpk(testData, subgroupSize, usl, lsl); // 四舍五入 SpcCalculator::RoundSpcData(xr, xs, cpk); // 创建结果对象 SpcResultJson result; result.XR = xr; result.XS = xs; result.Cpk = cpk; std::string json = result.ToJson().dump(2); std::cout << "\n单独序列化的结果:" << std::endl; std::cout << json << std::endl; } void RunSpcExample() { std::cout << "=== SPC 计算示例 ===" << std::endl; // 示例数据 std::vector testData = { 1.55, 1.58, 1.61, 1.60, 1.60, 1.58, 1.63, 1.63, 1.62, 1.63, 1.62, 1.63, 1.62, 1.59, 1.58, 1.58, 1.60, 1.61, 1.62, 1.63}; int subgroupSize = 5; double usl = 1.70; double lsl = 1.50; std::cout << "数据点数: " << testData.size() << std::endl; std::cout << "子组大小: " << subgroupSize << std::endl; std::cout << "规格上限: " << usl << std::endl; std::cout << "规格下限: " << lsl << std::endl; std::cout << std::endl; // 1. 计算 X-R 控制图 SpcDataXR xrResult = SpcCalculator::CalculateXR(testData, subgroupSize); std::cout << "X-R控制图结果:" << std::endl; std::cout << "X图中心线 (CL_X): " << xrResult.CL_X << std::endl; std::cout << "X图上控制限 (UCL_X): " << xrResult.UCL_X << std::endl; std::cout << "X图下控制限 (LCL_X): " << xrResult.LCL_X << std::endl; std::cout << "R图中心线 (CL_R): " << xrResult.CL_R << std::endl; std::cout << "R图上控制限 (UCL_R): " << xrResult.UCL_R << std::endl; std::cout << "R图下控制限 (LCL_R): " << xrResult.LCL_R << std::endl; std::cout << std::endl; // 2. 计算 X-S 控制图 SpcDataXS xsResult = SpcCalculator::CalculateXS(testData, subgroupSize); std::cout << "X-S控制图结果:" << std::endl; std::cout << "X图中心线 (CL_X): " << xsResult.CL_X << std::endl; std::cout << "X图上控制限 (UCL_X): " << xsResult.UCL_X << std::endl; std::cout << "X图下控制限 (LCL_X): " << xsResult.LCL_X << std::endl; std::cout << "S图中心线 (CL_S): " << xsResult.CL_S << std::endl; std::cout << "S图上控制限 (UCL_S): " << xsResult.UCL_S << std::endl; std::cout << "S图下控制限 (LCL_S): " << xsResult.LCL_S << std::endl; std::cout << std::endl; // 3. 计算过程能力指数 SpcDataCpk cpkResult = SpcCalculator::CalculateCpk(testData, subgroupSize, usl, lsl); std::cout << "过程能力指数结果:" << std::endl; std::cout << "Cp: " << cpkResult.Cp << std::endl; std::cout << "Cpk: " << cpkResult.Cpk << std::endl; std::cout << "Cpu: " << cpkResult.CPU << std::endl; std::cout << "Cpl: " << cpkResult.CPL << std::endl; std::cout << "Pp: " << cpkResult.Pp << std::endl; std::cout << "Ppk: " << cpkResult.Ppk << std::endl; std::cout << "Ca: " << cpkResult.Ca << std::endl; std::cout << std::endl; // 4. 计算其他统计指标 std::cout << "其他统计指标:" << std::endl; std::cout << "总体平均值: " << SpcCalculator::CalculateXbarbar(testData, subgroupSize) << std::endl; std::cout << "R-bar: " << SpcCalculator::CalculateRbar(testData, subgroupSize) << std::endl; std::cout << "S-bar: " << SpcCalculator::CalculateSbar(testData, subgroupSize) << std::endl; std::cout << "Cp值: " << SpcCalculator::CalculateCp(testData, subgroupSize, usl, lsl) << std::endl; std::cout << "Pp值: " << SpcCalculator::CalculatePp(testData, subgroupSize, usl, lsl) << std::endl; std::cout << std::endl; // 5. 计算直方图数据 std::vector frequencies; std::vector cumulativePercentages; HistogramCalculator::CalculateHistogram(testData, 6, frequencies, cumulativePercentages); std::cout << "直方图数据 (前3组):" << std::endl; for (int i = 0; i < std::min(3, static_cast(frequencies.size())); i++) { std::cout << "组" << i + 1 << ": 频数=" << frequencies[i] << ", 累计%=" << cumulativePercentages[i] << std::endl; } std::cout << std::endl; // 6. 获取 SPC 系数 const SpcCoefficient &coeff = SpcCoefficients::GetBySubgroupSize(subgroupSize); std::cout << "SPC系数 (n=" << subgroupSize << "):" << std::endl; std::cout << "A2: " << coeff.A2 << std::endl; std::cout << "D4: " << coeff.D4 << std::endl; std::cout << "d2 (L_D1): " << coeff.L_D1 << std::endl; } // ==================== 主函数 ==================== int main_spc() { try { // 运行示例 RunJsonExample_5_30(); std::cout << "\n\n"; RunSpcExample(); return 0; } catch (const std::exception &ex) { std::cerr << "错误: " << ex.what() << std::endl; return 1; } }