Files
smart_wasm/src/spc_core.cpp
2026-06-01 15:55:59 +08:00

1422 lines
44 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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<int, SpcCoefficient> SpcCoefficients::coefficientDict;
void SpcCoefficients::Initialize()
{
static bool initialized = false;
if (initialized)
return;
std::vector<SpcCoefficient> 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<double> &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<double> &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<double> &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<double> &values)
{
if (values.size() < 2)
return 0.0;
return Max(values) - Min(values);
}
double SpcUtils::StandardDeviation(const std::vector<double> &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<double> &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<std::vector<double>>();
}
if (j.contains("CL_Rk"))
{
data.CL_Rk = j["CL_Rk"].get<std::vector<double>>();
}
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<std::vector<double>>();
}
if (j.contains("CL_Sk"))
{
data.CL_Sk = j["CL_Sk"].get<std::vector<double>>();
}
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<std::vector<double>>();
}
if (j.contains("XkUp"))
{
data.XkUp = j["XkUp"].get<std::vector<double>>();
}
if (j.contains("XkDown"))
{
data.XkDown = j["XkDown"].get<std::vector<double>>();
}
if (j.contains("Yk"))
{
data.Yk = j["Yk"].get<std::vector<double>>();
}
if (j.contains("YkCount"))
{
data.YkCount = j["YkCount"].get<std::vector<double>>();
}
if (j.contains("NormalDistributionX"))
{
data.NormalDistributionX = j["NormalDistributionX"].get<std::vector<double>>();
}
if (j.contains("NormalDistributionY"))
{
data.NormalDistributionY = j["NormalDistributionY"].get<std::vector<double>>();
}
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<double> &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<double> &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<double> 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<double> &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<double> 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<double> 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<double> &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<double> 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<double> 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<int>(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 &param)
{
try
{
SpcTestData req_param = SpcTestData::FromJson(param);
// 使用测试数据
const std::vector<double> &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<double> &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<double> &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<double> 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<double> &data, int subgroupSize, double usl, double lsl)
{
double sigma = SpcUtils::StandardDeviationPopulation(data);
return (usl - lsl) / (6 * sigma);
}
double SpcCalculator::CalculateCpu(const std::vector<double> &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<double> 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<double> &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<double> 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<double> &data, int subgroupSize)
{
int k = data.size() / subgroupSize;
std::vector<double> subgroupMeans(k);
for (int i = 0; i < k; i++)
{
std::vector<double> 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<double> &data, int subgroupSize)
{
int k = data.size() / subgroupSize;
std::vector<double> subgroupRanges(k);
for (int i = 0; i < k; i++)
{
std::vector<double> 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<double> &data, int subgroupSize)
{
int k = data.size() / subgroupSize;
std::vector<double> subgroupStdDevs(k);
for (int i = 0; i < k; i++)
{
std::vector<double> 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<double> &data, int numBins,
std::vector<int> &frequencies, std::vector<double> &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<int>(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<double>(cumulative) / total * 100.0;
}
}
double HistogramCalculator::CalculateBinWidth(const std::vector<double> &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<std::vector<double>>();
}
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<SpcRequestParam>();
// *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<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
};
}
// ==================== 示例函数实现 ====================
void RunJsonExample_5_30()
{
std::cout << "=== SPC JSON 计算示例 (n=5, k=30) ===" << std::endl;
// 使用测试数据
const std::vector<double> &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<double> 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<int> frequencies;
std::vector<double> cumulativePercentages;
HistogramCalculator::CalculateHistogram(testData, 6, frequencies, cumulativePercentages);
std::cout << "直方图数据 (前3组):" << std::endl;
for (int i = 0; i < std::min(3, static_cast<int>(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;
}
}