1. 程式人生 > >教你用MSChart控制元件繪製正態分佈圖形

教你用MSChart控制元件繪製正態分佈圖形

一年多的“潛伏”也算是深資“特務”了,長時間看別人的部落格,自己卻沒有寫點東東,對不起那些園中勞碌的人。今天終於可以“洗牌”了做正常勞苦大眾。那也得感謝是專案交付期,有了“空擋”可以寫點什麼,讓大家拍磚。

      今天主講是的繪製正態分佈圖形所用的質量指標公式的,不注重講MSChart圖形控制元件的用法,MSChart圖形控制元件博園中有很多例項。正態分佈圖形所用的質量指標如下: USL(下規格線簡稱:下限)、USL(上限)、SIGMA(西格瑪)、XBAR(平均值)、SAMPLE DATA(樣本資料)、Zoom Multiple(縮放倍數)、Most Precision(最大精度)。

  1. Most Precision:最大精度,即小數點後面的位數長度。
     View Code
     1         /// <summary>
     2         /// 獲取資料序列的最大精度 (即小數點後面的位數長度) 3         /// </summary>
     4         /// <param name="sampleData">樣本資料</param>
     5         /// <returns></returns>
     6         public static int GetMostPrecision(List<decimal> sampleData)
     7         {
    
    8 if (sampleData == null || sampleData.Count == 0) 9 { 10 return 0; 11 } 12 13 int mostPrecision = 0; 14 int tempValue = 0; 15 16 foreach (decimal value in sampleData) 17 { 18 string data = Math.Abs(value
    ).ToString();
    19 int dateLength = data.Length; 20 int dotIndex = data.IndexOf("."); 21 22 if (dotIndex > 0) 23 { 24 tempValue = dateLength - (dotIndex + 1); 25 } 26 27 if (tempValue > mostPrecision) //取更大的精度 28 { 29 mostPrecision = tempValue; 30 } 31 } 32 33 return mostPrecision; 34 }
  2. Zoom Multiple:縮放倍數,為了增加圖形邊沿線的平滑度。  View Code
     1         /// <summary>
     2         /// 縮放倍數 3      /// </summary>
     4        /// <param name="mostPrecision"></param>
     5        /// <returns></returns>
     6         private static decimal ZoomMultiple(ref int mostPrecision)
     7         {
     8             decimal zoomMultiple = (decimal)Math.Pow(10, mostPrecision - 1);
     9 
    10             if (mostPrecision <= 2) //保證精度大於二的資料序列圖形的平滑
    11             {
    12                 mostPrecision = 4;
    13                 zoomMultiple = 100;
    14             }
    15 
    16             return zoomMultiple;
    17         }
  3. SAMPLE DATA:樣本資料是概率運算裡的一個概念。隨機抽取的部分用於計算出效能優良的數量。
  4. XBAR:這個大家好理解,也很好計算。即是所有樣本資料之和的平均值。  View Code
    1 double xbar = Math.Round(sampleData.Average(), mostPrecision);
  5. SIGMA:是一個希臘字母σ的中文譯音,在統計學中,代表標準偏差,用來對過程變異進行測量。  View Code
     1         /// <summary>
     2         /// 計算Sigma 3         /// </summary>
     4         /// <param name="sampleData">樣本資料</param>
     5         /// <param name="xbar">平均值</param>
     6         /// <returns></returns>
     7         public static double CalculateSigma(List<decimal> sampleData, double xbar)
     8         {
     9             double sigma = 0;
    10             int sampleCount = sampleData.Count;
    11             double powSum = 0;
    12 
    13             if (sampleData == null || sampleCount <= 2
    14 ) //樣本個數大於2計算才有意思
    15             {
    16                 return sigma;
    17             }
    18 
    19             foreach (double value in sampleData)
    20             {
    21                 powSum += Math.Pow(value - xbar, 2); //樣本值減去均值2的次冪相加。
    22             }
    23 
    24             sigma = Math.Sqrt(powSum / (sampleCount - 1));
    25 
    26             return sigma;
    27         }
  6. USL和LSL一般是抽樣人員事先設定好的,也可以用公式得到:  View Code
    1 double usl = xbar + 3 * sigma;//均值加3sigma
    2 double lsl = xbar - 3 * sigma;//均值減3sigma

     首先清除圖表Series集合上的資料點:

1 chart.Series[serieIndex].Points.Clear();

     X軸正、負界限以及正態公式係數:

1 int positiveLimit = (int)((xbar + 6 * sigma) * zoomMultiple); //X軸的正界限
2 int minusLimit = (int)((xbar - 6 * sigma) * zoomMultiple); //X軸的負界限
3 double coefficient = Math.Round(1 / Math.Sqrt(2 * Math.PI) / sigma, mostPrecision); //係數;如果計算需要精確,就不要四捨五入;建議:為了提高運算效率要四捨五入。

     根據公式生成正態圖形所需要的資料點:

 1 List<double> xValues = new List<double>();
 2 List<double> yValues = new List<double>();
 3  
 4 for (int x = minusLimit; x <= positiveLimit; x++)
 5        {
 6        //x軸縮小zoomMultiplex每隔1/zoomMultiple變化曲線變平滑
 7          double xValue = x / zoomMultiple;
 8          double yValue = coefficient * Math.Exp(Math.Pow((xValue - xbar), 2) / (-2 * Math.Pow(sigma, 2)));
 9           xValue = Math.Round(xValue, mostPrecision);
10           yValue = Math.Round(yValue, mostPrecision);
11            if (yValue > 0.0001)//可設為yValue > 0
12              {
13                 xValues.Add(xValue);
14                 yValues.Add(yValue);
15              }
16      }
17 
18 //為MSChart繫結資料值
19  chart.Series[serieIndex].Points.DataBindXY(xValues, yValues);

     為了確保圖形顯示完全,調整X和Y軸的最大值和最小值刻度:

 1  if (yValues.Count > 0)
 2      {
 3         yAxisMax = 0;
 4         return;
 5 
 6      }
 7 //將Y軸最大值放大倍作為
 8        double yMax = Math.Round(yValues.Max() * 1.1, args.MostPrecision);
 9        double xMin = xValues.Min();           
10        double xMax = xValues.Max();
11        double yMin = yValues.Min();
12        yAxisMax = yValues.Max();
13 
14     if (xMin > lsl)
15       {
16         xMin = lsl;
17       }
18     if (xMax < usl)
19       {
20        xMax = usl;
21      }
22 //設定軸值x軸加減極大極小值的1/zoomMultiple倍是為了圖形能全部繪製出來
23 chart.ChartAreas[0].AxisX.Minimum = (double)Math.Round(xMin - xMin * 1 / zoomMultiple, mostPrecision);
24 chart.ChartAreas[0].AxisX.Maximum = (double)Math.Round(xMax + xMax * 1 / zoomMultiple, mostPrecision);
25 chart.ChartAreas[0].AxisY.Minimum = (double)Math.Round(yMin, mostPrecision);
26 chart.ChartAreas[0].AxisY.Maximum = (double)Math.Round(yMax, mostPrecision);

       分別新增XBAR、USL、LSL閾值限函式如下:

 View Code
 1         /// <summary>
 2         /// 新增閾值線
 3      /// </summary>
 4         /// <param name="chartArea">圖形Area</param>

 5         /// <param name="lineName">線上顯示的名子</param>
 6         /// <param name="lineOffset">線在圖上的位置</param>
 7         /// <param name="lineWidth">線寬</param>
 8         /// <param name="lineColor">線的顏色</param>
 9         public void AddStripLine(ChartArea chartArea, string lineName, double lineOffset, double lineWidth, Color lineColor)
10         {
11             StripLine stripLine = new StripLine
12             {
13                 BackColor = lineColor,
14                 StripWidth = lineWidth,
15                 BackHatchStyle = ChartHatchStyle.DarkVertical,
16                 Text = lineName,
17                 TextAlignment = StringAlignment.Far,
18                 TextLineAlignment = StringAlignment.Center,
19                 IntervalOffset = lineOffset
20             };
21 
22             chartArea.AxisY.StripLines.Add(stripLine);
23         }

      最後是根據樣本值重置X軸的最大和最小刻度

 View Code
 1         /// <summary>
 2         /// 根據sampleData的最大和最小值重設X軸的最大和最小刻度 3       /// </summary>
 4         /// <param name="queueValue"></param>
 5         public static void ResetAxisBySampleData(List<decimal> sampleData, Chart chart)
 6         {
 7             if (sampleData == null || sampleData.Count <= 0)
 8             {
 9                 SwapValue(chart);
10                 return;
11             }
12 
13             double max = (double) sampleData.Max();
14             double min = (double) sampleData.Min();
15             double xMax = chart.ChartAreas[0].AxisX.Maximum;
16             double xMin = chart.ChartAreas[0].AxisX.Minimum;
17 
18             if (xMin > xMax)
19             {
20                 chart.ChartAreas[0].AxisX.Minimum = min;
21                 chart.ChartAreas[0].AxisX.Maximum = max;
22             }
23         }

以上是正態分佈圖所用到的指標和函式,正態直方圖所用到的指標和函式下次再講,時間倉促,寫的不細。如有不明的請發郵件,我們一起探討。Mail:[email protected] 如要轉發,請註明出處!