You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

589 lines
21 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Mesnac.Action.Feeding
{
// 摘要:
// 过程能力控制类
public class SixSigmaHelper
{
public static double d2 = 1.128;
public static double d3 = 1.693;
public static double d4 = 2.059;
public static double d5 = 2.326;
/// <summary>
/// 求和
/// </summary>
/// <param name="originalData">原始数据数组</param>
/// <returns></returns>
public static double GetSumValue(Double[] originalData)
{
Double sum = 0.0;
for (int i = 0; i < originalData.Length; i++)
{
sum = sum + originalData[i];
}
return DoubleFormat(sum);
}
/// <summary>
/// 求平均数
/// </summary>
/// <param name="originalData">原始数据数组</param>
/// <returns></returns>
public static Double GetAverageValue(Double[] originalData)
{
Double sum = 0.0;
Double ave = 0.0;
for (int i = 0; i < originalData.Length; i++)
{
sum = sum + originalData[i];
}
ave = sum / originalData.Length;
return DoubleFormat(ave);
}
/// <summary>
/// 按指定精度求平均值
/// </summary>
/// <param name="digits">精度,即保留的小数位数</param>
/// <param name="originalData"原始数据></param>
/// <returns></returns>
public static Double GetAverageValue(int digits, Double[] originalData)
{
Double sum = 0.0;
Double ave = 0.0;
for (int i = 0; i < originalData.Length; i++)
{
sum = sum + originalData[i];
}
ave = sum / originalData.Length;
return DoubleFormat(digits, ave);
}
/// <summary>
/// 获取整体平均值:先分组,计算组内平均值,然后计算整体平均值
/// </summary>
/// <param name="digits">精度,小数位数</param>
/// <param name="groupSize">组大小</param>
/// <param name="originalData"> 原始数据</param>
/// <returns></returns>
public static Double GetTotalAveByGroup(int digits, int groupSize, Double[] originalData)
{
Double[] groupAve = GetGroupAve(digits, groupSize, originalData);
return SixSigmaHelper.GetAverageValue(digits, groupAve);
}
/// <summary>
/// 获取子组平均数,以数组形式返回
/// </summary>
/// <param name="digits">精度,小数位数</param>
/// <param name="groupSize">组大小</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回子组平均值</returns>
public static Double[] GetGroupAve(int digits, int groupSize, Double[] originalData)
{
Double groupNum = Math.Ceiling(Convert.ToDouble(originalData.Length / groupSize));
Double[] groupAve = new Double[Convert.ToInt32(groupNum)];
for (int i = 0; i < Convert.ToInt32(groupNum); i++)
{
int index = i * groupSize;
Double[] temp = new Double[groupSize];
for (int j = 0; j < groupSize; j++)
{
temp[j] = originalData[index + j];
}
groupAve[i] = SixSigmaHelper.GetAverageValue(digits, temp);
}
return groupAve;
}
/// <summary>
/// 求整体标准差
/// </summary>
/// <param name="originalData">原始数据</param>
/// <returns>返回标准差</returns>
public static Double GetTotalStdDev(Double[] originalData)
{
Double ave = 0.0;
Double stdDev = 0.0;
if (originalData.Length == 1 && originalData[0] == 0.0)
{
return stdDev = 0.0;
}
ave = GetAverageValue(originalData);
for (int i = 0; i < originalData.Length; i++)
{
stdDev = (Double)(stdDev + Math.Pow((originalData[i] - ave), 2));
}
stdDev = (Double)Math.Sqrt(stdDev / (originalData.Length - 1));
return DoubleFormat(stdDev);
}
/// <summary>
/// 按指定精度获取标准差
/// </summary>
/// <param name="digits">精度,即小数位数</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回标准差</returns>
public static Double GetStdDev(int digits, Double[] originalData)
{
Double ave = 0.0;
Double stdDev = 0.0;
ave = GetAverageValue(originalData);
for (int i = 0; i < originalData.Length; i++)
{
stdDev = (Double)(stdDev + Math.Pow((originalData[i] - ave), 2));
}
stdDev = (Double)Math.Sqrt(stdDev / (originalData.Length - 1));
return DoubleFormat(digits, stdDev);
}
/// <summary>
/// 求移动极差均值
/// </summary>
/// <param name="size">子组容量</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回移动极差均值</returns>
public static Double GetMoveRangeMean(int size, Double[] originalData)
{
Double moveSum = 0.0;
Double moveAve = 0.0;
Double[] range = new Double[originalData.Length - (size - 1)];
for (int i = (size - 1); i < originalData.Length; i++)
{
Double[] temp = new Double[size];
int count = size;
int idx = 0;
do
{
temp[idx] = originalData[i - (count - 1)];
idx++;
count--;
} while ((count > 0));
range[i - (size - 1)] = (Double)Math.Abs(GetArrMax(temp) - GetArrMin(temp));
}
for (int i = 0; i < range.Length; i++)
{
moveSum = moveSum + range[i];
}
moveAve = moveSum / range.Length;
return DoubleFormat(moveAve);
}
/// <summary>
/// 求组内标准差
/// </summary>
/// <param name="size">子组容量</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回组内标准差</returns>
public static Double GetInGroupStdDev(int size, Double[] originalData)
{
Double gourpStdDev = 0.0;
Double moveAve = GetMoveRangeMean(size, originalData);
switch (size)
{
case 2:
gourpStdDev = (Double)(moveAve / d2);
break;
case 3:
gourpStdDev = (Double)(moveAve / d3);
break;
case 4:
gourpStdDev = (Double)(moveAve / d4);
break;
case 5:
gourpStdDev = (Double)(moveAve / d5);
break;
default:
gourpStdDev = (Double)(moveAve / d2);
break;
}
return DoubleFormat(gourpStdDev);
}
/// <summary>
/// 获取整体正态分布曲线数组值
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回整体正态分布曲线数组值</returns>
public static Dictionary<String, Object> GetNormalDistribution(Double target, Double[] original)
{
Dictionary<String, Object> json = new Dictionary<String, Object>();
Double sigma = GetTotalStdDev(original);
Double lcl = DoubleFormat(target - 3 * sigma);
Double ucl = DoubleFormat(target + 3 * sigma);
int idx = 10;
Double plus = 0.0;
plus = ((double)((int)(ucl - lcl + 1))) / 10;
Double[] categories = new Double[idx];
Double[] values = new Double[idx];
categories[0] = lcl;
for (int i = 1; i < idx; i++)
{
categories[i] = DoubleFormat(categories[i - 1] + plus);
}
for (int i = 0; i < idx; i++)
{
values[i] = 0.0;
}
for (int i = 1; i < categories.Length; i++)
{
values[i] = DoubleFormat(1
/ ((Math.Sqrt(2 * Math.PI) * GetTotalStdDev(original)))
* Math.Pow(
Math.E,
-Math.Pow((categories[i] - GetAverageValue(original)), 2)
/ (2 * Math
.Pow(GetTotalStdDev(original), 2))));
}
json.Add("categories", categories);
json.Add("values", values);
return json;
}
/// <summary>
/// 获取组内正态分布曲线数组值
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回组内正态分布曲线数组值</returns>
public static Dictionary<String, Object> GetInGroupNormalDistribution(Double target, Double[] original)
{
Dictionary<String, Object> json = new Dictionary<String, Object>();
Double sigma = GetTotalStdDev(original);
Double lcl = DoubleFormat(target - 3 * sigma);
Double ucl = DoubleFormat(target + 3 * sigma);
int idx = 10;
Double plus = 0.0;
plus = ((double)((int)(ucl - lcl + 1))) / 10;
Double[] categories = new Double[idx];
Double[] values = new Double[idx];
Double inGroupStdDev = GetInGroupStdDev(2, original);
Double ave = GetAverageValue(original);
categories[0] = lcl;
for (int i = 1; i < idx; i++)
{
categories[i] = DoubleFormat(categories[i - 1] + plus);
}
for (int i = 0; i < idx; i++)
{
values[i] = 0.000000;
}
for (int i = 1; i < categories.Length; i++)
{
values[i] = DoubleFormat(1
/ ((Math.Sqrt(2 * Math.PI) * inGroupStdDev))
* Math.Pow(
Math.E,
-Math.Pow((categories[i] - ave), 2)
/ (2 * Math.Pow(inGroupStdDev, 2))));
}
json.Add("categories", categories);
json.Add("values", values);
return json;
}
/// <summary>
/// 获取数据分布情况
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回数据分布情况</returns>
public static Dictionary<String, Object> GetDataDistribution(Double target, Double[] original)
{
Dictionary<String, Object> json = new Dictionary<String, Object>();
Double sigma = GetTotalStdDev(original);
Double lcl = DoubleFormat(target - 3 * sigma);
Double ucl = DoubleFormat(target + 3 * sigma);
int idx = 10;
Double plus = 0.0;
plus = ((double)((int)(ucl - lcl + 1))) / 10;
Double[] categories = new Double[idx];
Double[] values = new Double[idx];
String[] test = new String[idx];
categories[0] = lcl;
for (int i = 1; i < idx; i++)
{
categories[i] = DoubleFormat(categories[i - 1] + plus);
}
for (int i = 0; i < idx; i++)
{
values[i] = 0.0;
test[i] = "";
}
for (int i = 0; i < original.Length; i++)
{
for (int j = 0; j < categories.Length; j++)
{
if (categories[j] - 0.5 < original[i] && original[i] <= categories[j] + 0.5)
{
values[j] += 1;
test[j] += original[i] + ",";
}
}
}
for (int i = 0; i < idx; i++)
{
values[i] = values[i] / 100;
}
json.Add("categories", categories);
json.Add("values", values);
return json;
}
/// <summary>
/// 无偏移过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移过程能力指数</returns>
public static Double GetPP(Double upperT, Double lowerT, Double[] original)
{
Double pp = new Double();
Double sigma = GetTotalStdDev(original);
pp = (upperT - lowerT) / (6 * sigma);
return DoubleFormat(pp);
}
/// <summary>
/// 无偏移下单限过程能力指数
/// </summary>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移下单限过程能力指数</returns>
public static Double GetPPL(Double lowerT, Double[] original)
{
Double ppl = new Double();
Double sigma = GetTotalStdDev(original);
Double ave = GetAverageValue(original);
ppl = (ave - lowerT) / (3 * sigma);
return DoubleFormat(ppl);
}
/// <summary>
/// 无偏移上单限过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移上单限过程能力指数</returns>
public static Double GetPPU(Double upperT, Double[] original)
{
Double ppl = new Double();
Double sigma = GetTotalStdDev(original);
Double ave = GetAverageValue(original);
ppl = (upperT - ave) / (3 * sigma);
return DoubleFormat(ppl);
}
/// <summary>
/// 有偏移过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回有偏移过程能力指数</returns>
public static Double getPPK(Double upperT, Double lowerT, Double[] original)
{
Double ppl = GetPPL(lowerT, original);
Double ppu = GetPPU(upperT, original);
return DoubleFormat(ppl > ppu ? ppu : ppl);
}
/// <summary>
/// 无偏移短期过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移短期过程能力指数</returns>
public static Double GetInGroupCP(Double upperT, Double lowerT, Double[] original)
{
Double cp = new Double();
Double sigma = GetInGroupStdDev(2, original);
if (sigma == 0)
{
cp = 0;
}
else
{
cp = (upperT - lowerT) / (6 * sigma);
}
return DoubleFormat(cp);
}
/// <summary>
/// 无偏移下单限短期过程能力指数
/// </summary>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移下单限短期过程能力指数</returns>
public static Double GetInGroupCPL(Double lowerT, Double[] original)
{
Double cpl = new Double();
Double sigma = GetInGroupStdDev(2, original);
if (sigma == 0)
{
return 0;
}
else
{
Double ave = GetAverageValue(original);
cpl = (ave - lowerT) / (3 * sigma);
return DoubleFormat(cpl);
}
}
/// <summary>
/// 无偏移上单限短期过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="original">原始数据</param>
/// <returns>反回无偏移上单限短期过程能力指数</returns>
public static Double GetInGroupCPU(Double upperT, Double[] original)
{
Double cpu = new Double();
Double sigma = GetInGroupStdDev(2, original);
if (sigma == 0)
{
return 0;
}
else
{
Double ave = GetAverageValue(original);
cpu = (upperT - ave) / (3 * sigma);
return DoubleFormat(cpu);
}
}
/// <summary>
/// 有偏移短期过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回有偏移短期过程能力指数</returns>
public static Double GetInGroupCPK(Double upperT, Double lowerT, Double[] original)
{
Double cpl = GetInGroupCPL(lowerT, original);
Double cpu = GetInGroupCPU(upperT, original);
return DoubleFormat(cpl > cpu ? cpu : cpl);
}
/// <summary>
/// 自然上限
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回自然上限</returns>
public static Double GetUCL(Double target, Double[] original)
{
Double sigma = GetTotalStdDev(original);
return DoubleFormat(target + 3 * sigma);
}
/// <summary>
/// 自然下限
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回自然下限</returns>
public static Double GetLCL(Double target, Double[] original)
{
Double sigma = GetTotalStdDev(original);
return DoubleFormat(target - 3 * sigma);
}
/// <summary>
/// 最小值
/// </summary>
/// <param name="array">原始数据数组</param>
/// <returns>返回最小值</returns>
public static Double GetArrMin(Double[] array)
{
Double min = array[0];
for (int i = 0; i < array.Length; i++)
{
if (min > array[i])
min = array[i];
}
return min;
}
/// <summary>
/// 最大值
/// </summary>
/// <param name="array">原始数据数组</param>
/// <returns>返回最大值</returns>
public static Double GetArrMax(Double[] array)
{
Double max = array[0];
for (int i = 0; i < array.Length; i++)
{
if (max < array[i])
max = array[i];
}
return max;
}
/// <summary>
/// 数据格式化默认保留5位小数
/// </summary>
/// <param name="d">要格式化的数据</param>
/// <returns>返回格式化后的数据</returns>
public static Double DoubleFormat(Double d)
{
double result = 0.0;
if (double.TryParse(d.ToString(), out result))
{
Decimal b = new Decimal(d);
Double formatD = Convert.ToDouble(Math.Round(b, 5));
//b.setScale(5, BigDecimal.ROUND_HALF_UP).doubleValue();
return formatD;
}
else
{
return 0.0;
}
}
/// <summary>
/// 按指定精度进行数据格式化
/// </summary>
/// <param name="digits">精度,小数位数</param>
/// <param name="d">要格式化的数据</param>
/// <returns>返回格式化后的数据</returns>
public static Double DoubleFormat(int digits, Double d)
{
double result = 0.0;
if (double.TryParse(d.ToString(), out result))
{
Decimal b = new Decimal(d);
Double formatD = Convert.ToDouble(Math.Round(b, digits));
//Double formatD = b.setScale(digits, BigDecimal.ROUND_HALF_UP).doubleValue();
return formatD;
}
else
{
return 0.0;
}
}
}
}