/// <Summary> /// provide normal image data and /// </ Summary> public class StandardDistribution { /// <Summary> /// sample data /// </ Summary> public List <Double > Xs {GET; Private SET;} public StandardDistribution (List <Double> Xs) { this.Xs = Xs; Average = Xs.Average (); Variance = GetVariance (Xs); IF (Variance == 0) the throw new new Exception ( "variance 0"); // this case does not need to count each sample because the data are the same, the interface can prompt accordingly StandardVariance = Math.Sqrt (variance); } /// <Summary> /// variance / the square of the standard deviation /// </ Summary> /// </ Summary> // / <param name = "x" > </ param> /// <returns></returns> Double GET Variance {public; Private SET;} /// <Summary> /// standard deviation /// </ Summary> public Double StandardVariance {GET; Private SET;} /// <Summary> /// arithmetic mean / mathematical expectation /// </ Summary> public Double Average {GET; Private SET;} /// <Summary> ///. 1 / (square root of 2 [pi]) values /// </ Summary> public static Double InverseSqrt2PI = . 1 / Math.Sqrt (2 * Math.PI); /// <Summary> /// Get the specified X value calculation formula Y value is too distributed public Double GetGaussianDistributionY (Double X) { double PowOfE = -(Math.Pow(Math.Abs(x - Average), 2) / (2 * Variance)); double result = (StandardDistribution.InverseSqrt2PI / StandardVariance) * Math.Pow(Math.E, PowOfE); return result; } /// <summary> /// 获取正太分布的坐标<x,y> /// </summary> /// <returns></returns> public List<Tuple<double, double>> GetGaussianDistributionYs() { List<Tuple<double, double>> XYs = new List<Tuple<double, double>>(); Tuple<double, double> xy = null; foreach (double x in Xs) { = new new Tuple XY <Double, Double> (X, GetGaussianDistributionY (X)); XYs.Add (XY); } return XYS; } /// <Summary> /// Gets a list of integers variance /// </ summary> data list /// <param name = "src" > to calculate the variance of the </ param> /// <Returns> </ Returns> public static Double GetVariance (list <Double> the src) { Double the src = Average. Average (); Double SumOfSquares = 0; src.ForEach (X => {SumOfSquares Math.Pow + = (X - Average, 2);}); return SumOfSquares / src.Count;// variance } /// <Summary> /// Get a list of integers variance /// </ Summary> /// <param name = " src ">To calculate the variance of the data list </ param> /// <returns></returns> public static float GetVariance(List<float> src) { float average = src.Average(); double SumOfSquares = 0; src.ForEach(x => { SumOfSquares += Math.Pow(x - average, 2); }); return (float)SumOfSquares / src.Count;//方差 } /// <summary> /// 画学生成绩的正态分布 /// </summary> /// <param name = "the Width"> </ param> /// <param name = "Height" > </ param> /// <param name = "Scores" > fraction, Y value </ param> /// <param name="familyName"></param> /// <returns></returns> public Bitmap GetGaussianDistributionGraph(int Width, int Height,int TotalScore, string familyName = "宋体") // score abscissa; the value of the normal distribution of the longitudinal axis { = New new Bitmap Bitmap Bitmap (the Width, the Height); Graphics GDI = Graphics.FromImage (Bitmap); gdi.Clear (Color.White); gdi.SmoothingMode = SmoothingMode.HighQuality; gdi.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; gdi.PixelOffsetMode = PixelOffsetMode.HighQuality; List <Tuple <Double, scores Double >> = GetGaussianDistributionYs () the OrderBy (X => x.Item1) .ToList ();. // Sort convenient connection between the rear dots ensure low score the left float YHeight = 0.8F * Height; // relative to the lower left corner indicating YHeight * 0.9F maxY a float xWidth the Width * = 0.9F; // relative to the lower left corner indicating xWidth * 0.9F maxX a float marginX = (the Width - xWidth) / 2F; // x-axis relative to the left and right edges of pixel image float marginY = (Height - YHeight) / 2F; // y-axis pixel images vertically opposite edges of PointF leftTop of PointF new new = (marginX, marginY); of PointF leftBottom of PointF new new = (marginX, marginY YHeight +); // coordinate axis bottom left PointF rightBottom = new PointF (marginX + xWidth, marginY + YHeight); // bottom right axis gdi.DrawLine (Pens.Gray, leftBottom, rightBottom) ; // x -axis gdi.DrawLine (Pens.Gray, leftBottom, leftTop) ; // Y -axis // two arrows four line 6 is also required to coordinate 4 coordinate PointF YArrowLeft = new PointF (leftTop.X - 5, leftTop.Y + 5) ; of PointF YArrowRight of PointF new new = (+ leftTop.X. 5, leftTop.Y +. 5); of PointF XArrowTop of PointF new new = (rightBottom.X -. 5, rightBottom.Y -. 5); of PointF XArrowBottom of PointF new new = (rightBottom.X -. 5 , rightBottom.Y +. 5); gdi.DrawLine (Pens.Gray, rightBottom, XArrowBottom); a float unitX = 0.0F; // X-axis conversion ratio gdi.DrawLine (Pens.Gray, leftTop, YArrowLeft); gdi.DrawLine (Pens.Gray, leftTop, YArrowRight); gdi.DrawLine (Pens.Gray, rightBottom, XArrowTop); a float Unity = 0.0F; // convert the Y-axis ratio List <PointF> pointFs = ConvertToPointF ( scores, xWidth * 0.9F, YHeight * 0.9F, leftTop, out unitX, out unitY); // score and probability of converting into coordinates gdi.DrawCurve (Pens.Black, pointFs.ToArray (), 0.0F); // cardinal spline // average parallel to the Y axis of PointF avg_top of PointF new new = (leftTop.X + (a float) * average unitX, leftTop.Y); of PointF avg_bottom of PointF new new = (leftTop. + X-(a float) * Average unitX, leftBottom.Y); gdi.DrawLine (Pens.Black, avg_top, avg_bottom); gdi.DrawString (string.Format ( "{0} ", ((float) Average) .ToString (" F2 ")), new Font (" Arial ", 11), Brushes.Black, avg_bottom.X, avg_bottom.Y-25); // write in the expectation and variance The horizontal axis below the middle = New new variance_pf of PointF of PointF (leftBottom.X + (xWidth / 2) -120, avg_bottom.Y + 25); gdi.DrawString (string.Format ( "expected: {0}; variance: {1}", (( float) Average) .ToString ( "F2") , Variance.ToString ( "F2")), new Font ( " Arial",. 11), Brushes.Black, variance_pf.X, variance_pf.Y); // the minimum and maximum score fraction 9 is divided into sections marked on the abscissa axis Double Scores.Min = minX (X => x.Item1); Double maxX = Scores.Max (X => x.Item1); Double perSegment = the Totalscore / 10; // (maxX - minX) / 9F; // score for each segment represented by List <double> segs = new List <double> (); // for each segment of the boundary value abscissa segs.Add (leftBottom.X + ( a float) minX * unitX); for (int I =. 1; I <. 11; I ++) { segs.Add (leftBottom.X + (a float) unitX minX * + * I * perSegment unitX); } for (int I = 0; I <. 11; I ++) { gdi.DrawPie (Pens.Black, (a float) SEGs [ I] -. 1, leftBottom.Y -. 1, 2, 2, 0, 360); . gdi.DrawString (string.Format ( "{0}", ((+ perSegment * minX (I))) the ToString ( "F0 ")), new Font (" Arial ",. 11), Brushes.Black, (a float) SEGs [I] - 15, leftBottom.Y +. 5); } return Bitmap; } /// <Summary> /// the data into coordinates /// </ Summary> /// <param name = "Scores"> </ param> /// <param name = "X-"> maximum use abscissa </param> /// <name = "Y" param > using the longest longitudinal </ param> /// <param name = "leftTop"> origin the upper left corner </ param> /// <Returns> </ Returns> Private static List <of PointF> ConvertToPointF (List <Tuple <Double, Double >> Scores, X-a float, a float the Y, of PointF leftTop, OUT unitX a float, a float Unity OUT) { Double Scores.Max = maxY (X => x.Item2); maxX = Scores.Max Double (X => x.Item1); List <of PointF> = new new Result List <of PointF> (); a float paddingY the Y * = 0.01F; a float * X-paddingX = 0.01F; Unity = (a float) ((Y - paddingY) / maxY ); // units out of the vertical axis represents the calculated desired height ordinate need leftTop.Y + (Y-item2 * unitY ) + paddingY unitX = (float) ((X - paddingX) / maxX); // units out of the horizontal axis represents the desired width calculated abscissa ITEM1 * + unitX need leftTop.X of PointF of PointF new new PF = (); the foreach (Tuple < Double, Double> in Item Scores) { PF of PointF new new = (leftTop.X + (a float) item.Item1 * unitX, leftTop.Y + (the Y - (a float) item.Item2 Unity *) + paddingY); result.Add (PF); } return Result; } }
transfer:
StandardDistribution mathX = new StandardDistribution(scores); Bitmap bitmap = mathX.GetGaussianDistributionGraph(800, 480, totalScore); bitmap.Save("tt.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
FIG normal test data generation: