AbstractDistribution distr;		//Распределение, для которого проверяется гипотеза

		/// <summary>
		/// Создает новый объект класса CheckDistributionForm с заданным распределением
		/// </summary>
		/// <param name="distr">Объект распределения</param>
		public CheckDistributionForm(AbstractDistribution distr)
		{
			InitializeComponent();

			//Сохраняем распределение. Отображаем его имя
			this.distr = distr;
			lblDistrType.Text = distr.Name;


			//Заголовки графиков
			if(distr.DistributionType==DistributionType.DISCRETE)
				graphEmp.GraphPane.Title.Text = "Полигон относительных частот";
			else
				graphEmp.GraphPane.Title.Text = "Гистограмма относительных частот";

			graphTheor.GraphPane.Title.Text = "Теоретическая функция распределения";

			//Отображает полигон относительных частот и график теоретического закона распределения
			//draw_distribution(graphEmp, distr.Distribution);

			draw_emp_graph(graphEmp, distr);
			draw_distribution(graphTheor, distr.GetTheoreticalFreq());

			//Делаем одинаковый масштаб
			double min_1 = graphTheor.GraphPane.YAxis.Scale.Min;
			double min_2 = graphEmp.GraphPane.YAxis.Scale.Min;
			double max_1 = graphTheor.GraphPane.YAxis.Scale.Max;
			double max_2 = graphEmp.GraphPane.YAxis.Scale.Max;

			graphTheor.GraphPane.YAxis.Scale.Min = Math.Min(min_1, min_2);
			graphEmp.GraphPane.YAxis.Scale.Max = Math.Max(max_1, max_2);
			graphEmp.GraphPane.YAxis.Scale.MajorStep = graphTheor.GraphPane.YAxis.Scale.MajorStep;
			graphEmp.GraphPane.YAxis.Scale.MinorStep = graphTheor.GraphPane.YAxis.Scale.MinorStep;

			graphTheor.AxisChange();
			graphTheor.Invalidate();

			//Загружает значения уровней значимости в ComboBox
			cbAlpha.DataSource = CriticalPirsonCriterion.GetSignificanceLevel();

			//Отображаем формулу распределения
			pboxFunction.BackgroundImage = distr.Funtion;

			//Отображаем точечные оценки
			//Магия
			foreach (DataGridViewColumn col in gridPointValues.Columns)
				col.DataPropertyName = col.Name;

			var bs = new BindingSource();
			gridPointValues.RowTemplate.Height = 68;
			bs.DataSource = distr.PointValues.Select(x => new { ParamName = x.ParamName, Formula = x.Formula, Value=x.Value }).ToList();
			gridPointValues.DataSource = bs;
			gridPointValues.Columns["Value"].DefaultCellStyle.Format = "N2";


			//Настройка числа знаков после запятой для таблицы расчета
			gridCalcTable.Columns["Pi"].DefaultCellStyle.Format = "N2";
			gridCalcTable.Columns["ni"].DefaultCellStyle.Format = "N2";
			gridCalcTable.Columns["sums"].DefaultCellStyle.Format = "N2";

		}
		///////////////////////////// ПОСТРОЙКА ГРАФИКОВ ////////////////////////////////

		//Строит график ряда
		//Для дискретного распределения строится только полигон относительных частот
		//Для непрерывного - гистограмма, а на ее фоне  - полигон, но деленый на ширину интервала
		void draw_emp_graph(ZedGraphControl graph, AbstractDistribution distr)
		{
			if (distr.DistributionType == DistributionType.DISCRETE)
				draw_distribution(graph, distr.Distribution.GroupRelFreq);
			else
			{
				//Непрерывное
				//Гистограмма
				HistogramPlotter plotter = new HistogramPlotter(graph);
				plotter.Plot(distr.Distribution.IntervalRelFreq, Color.FromArgb(30, 230, 126, 34));

				//Полигон
				double interval = 1;
				var points = new PointPairList();
				for (int i = 0; i < distr.Distribution.GroupRelFreq.Count; i++)
				{
					var val = distr.Distribution.GroupRelFreq.ElementAt(i);
					if (i < distr.Distribution.GroupRelFreq.Count - 1)
						interval = distr.Distribution.GroupRelFreq.ElementAt(i + 1).Key - val.Key;

					points.Add(val.Key, val.Value / interval);
				}

				var pane = graph.GraphPane;

				var curve = pane.AddCurve("", points, Color.FromArgb(255, 39, 174, 96), SymbolType.Default);


				graph.AxisChange();
				graph.Invalidate();
			}
		}
		//Расчитывает число степеней свободы
		int calc_degrees_of_freedom(AbstractDistribution distr)
		{
			return distr.Distribution.Count -   //Число элементов группированного ряда == число интервалов
				   distr.PointValues.Count -	  //число точечных значений - число элементов, которые мы оцениваем по выборке
				   1;
		}
		//Расчитывает наблюдаемое значение критерия
		double calc_pirson(AbstractDistribution distr)
		{
			//Получаем значения теоретических вероятностей и частот
			var probs = distr.CalcProbablities();
			double pirson = 0;
			int n = distr.Count;
			Debug.WriteLine("n={0}", n.ToString());

			//Очищаем таблицу
			gridCalcTable.Rows.Clear();
			
			//Расчитываем критерий пирсонаы
			foreach (var el in probs)
			{
				Debug.WriteLine(n * el.Pi);
				double slag = Math.Pow(el.Mi - n * el.Pi, 2) / (n * el.Pi);
				pirson += slag;

				//Заполняем таблицу расчетов
				var row_index = gridCalcTable.Rows.Add();
				var row = gridCalcTable.Rows[row_index];
			
				row.Cells["interval"].Value = el.XValue;
				row.Cells["Pi"].Value = el.Pi;
				row.Cells["ni"].Value = el.Mi;
				row.Cells["sums"].Value = slag;
			}

			return pirson;
		}
		//Ручная проверка
		//Только считает критерий
		void manual_ceck(AbstractDistribution distr)
		{
			txtPirsonVis.Text = calc_pirson(distr).ToString("N4");
			var frm = new PirsonTableForm();
			frm.Show();
		}
		/////////////////////////////////// РАСЧЕТЫ /////////////////////////////////////

		//Автоматическая проверка гипотезы
		//Считает критерий, степени свободы, критическое значение 
		//и сам сравнивает
		void auto_check(AbstractDistribution distr)
		{
			//Вычисляем значения
			double pirson_vis = calc_pirson(distr);
			int degrees_of_freedom = calc_degrees_of_freedom(distr);
			double pirson_crit = CriticalPirsonCriterion.GetCriticalValue((double)cbAlpha.SelectedItem, degrees_of_freedom);

			//Отображаем значения
			txtPirsonVis.Text = pirson_vis.ToString("N4");
			txtDegreesOfFreedom.Text = degrees_of_freedom.ToString();
			txtPirsonCrit.Text = pirson_crit.ToString("N4");

			//Пишемм вывод
			if(pirson_vis<pirson_crit)
			{
				labelResult.Text = "НЕ ОТВЕРГАЕМ ГИПОТЕЗУ";
				labelResult.ForeColor = Color.Green;
			}
			else
			{
				labelResult.Text = "ОТВЕРГАЕМ ГИПОТЕЗУ";
				labelResult.ForeColor = Color.Red;
			}
			labelResult.Visible = true;
		}