// ОК private void ApplyButton_Click(object sender, EventArgs e) { // Контроль диапазона if ((StepValue.Value == 0) || ((uint)(Math.Abs(EndValue.Value - StartValue.Value) / StepValue.Value) + 1 > DiagramData.MaxDataRows) || (EndValue.Value == StartValue.Value)) { MessageBox.Show(Localization.GetText("IncorrectRangeError", language), ProgramDescription.AssemblyTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } // Блокировка this.Enabled = false; // Заполнение for (int c = 0; c < CurvesList.Items.Count; c++) { // Получение цепочки вычисления LexemesExtractor le = new LexemesExtractor(CurvesList.Items[c].ToString()); EvaluationChainAssembler eca = new EvaluationChainAssembler(le); ExpressionEvaluator ee; // Подготовка y.Add(new List <double> ()); // Генерация for (double i = (double)Math.Min(StartValue.Value, EndValue.Value); i < (double)Math.Max(StartValue.Value, EndValue.Value); i += (double)StepValue.Value) { if (c == 0) { x.Add(i); } ee = new ExpressionEvaluator(eca, i); y[y.Count - 1].Add(ee.Result); } // Последнее значение if (c == 0) { x.Add((double)Math.Max(StartValue.Value, EndValue.Value)); } ee = new ExpressionEvaluator(eca, (double)Math.Max(StartValue.Value, EndValue.Value)); y[y.Count - 1].Add(ee.Result); // Название столбца columnsNames.Add(CurvesList.Items[c].ToString()); } // Завершение cancelled = false; this.Close(); }
/// <summary> /// Конструктор. Выполняет сборку цепочки вычислений /// </summary> public EvaluationChainAssembler(LexemesExtractor ExpressionLexemesExtractor) { // Контроль сборки if ((ExpressionLexemesExtractor.FollowingStatus != LexemesFollowingMatrix.LexemesFollowingStatuses.Ok) || (ExpressionLexemesExtractor.ExpressionStatus != LexemesExtractor.ExpressionStatuses.Ok)) { return; } // Формирование массива приоритетов List <int> links = new List <int> (); int multiplier = 10000; for (int i = 0; i < ExpressionLexemesExtractor.ExtractedLexemes.Count; i++) { switch (ExpressionLexemesExtractor.ExtractedLexemes[i].LexemeType) { // Установка уровня вложенности case Lexeme.LexemeTypes.LeftParenthesis: multiplier += 10000; break; case Lexeme.LexemeTypes.RightParenthesis: multiplier -= 10000; break; // Установка приоритетов для функций и операций case Lexeme.LexemeTypes.Sinus: case Lexeme.LexemeTypes.Cosinus: case Lexeme.LexemeTypes.Tangens: case Lexeme.LexemeTypes.Cotangens: case Lexeme.LexemeTypes.Arcsinus: case Lexeme.LexemeTypes.Arccosinus: case Lexeme.LexemeTypes.Arctangens: case Lexeme.LexemeTypes.Arccotangens: case Lexeme.LexemeTypes.NaturalLogarithm: case Lexeme.LexemeTypes.Abs: links.Add(multiplier + 5000 + i); break; case Lexeme.LexemeTypes.Exponentiation: links.Add(multiplier + 4000 + i); break; case Lexeme.LexemeTypes.Division: links.Add(multiplier + 3000 + i); break; case Lexeme.LexemeTypes.Multiplication: links.Add(multiplier + 2000 + i); break; case Lexeme.LexemeTypes.Minus: links.Add(multiplier + 1000 + i); break; case Lexeme.LexemeTypes.Plus: links.Add(multiplier + 0 + i); break; // Установка прямых ссылок на операнды case Lexeme.LexemeTypes.E: case Lexeme.LexemeTypes.Pi: case Lexeme.LexemeTypes.Number: case Lexeme.LexemeTypes.Variable: links.Add(i); break; // А такого быть не должно: класс LexemesExtractor должен это исключить case Lexeme.LexemeTypes.Unknown: throw new Exception("Достигнуто предвиденное исключение. Для коррекции необходимо обратиться к автору программы"); } } // Сборка цепочки int max, maxIndex; while (true) { // Поиск максимального приоритета max = maxIndex = 0; for (int i = 0; i < links.Count; i++) { if (max < links[i]) { max = links[i]; maxIndex = i; } } // Условие прерывания if (max < 1000) { break; } // Обработка операций (любой сбой на этом шаге означает кривизну предыдущих обработок) switch (ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000].LexemeType) { // Обработка функций case Lexeme.LexemeTypes.Sinus: case Lexeme.LexemeTypes.Cosinus: case Lexeme.LexemeTypes.Tangens: case Lexeme.LexemeTypes.Cotangens: case Lexeme.LexemeTypes.Arcsinus: case Lexeme.LexemeTypes.Arccosinus: case Lexeme.LexemeTypes.Arctangens: case Lexeme.LexemeTypes.Arccotangens: case Lexeme.LexemeTypes.NaturalLogarithm: case Lexeme.LexemeTypes.Abs: if (links[maxIndex + 1] >= 0) { // По факту chain.Add(new EvaluationChainElement(ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000], ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex + 1] % 1000])); } else { // По ссылке (ссылки хранятся в отрицательных числах со смещением chain.Add(new EvaluationChainElement(ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000], (uint)(-links[maxIndex + 1] - 1))); } // То же самое if (!chain[chain.Count - 1].IsInited) { throw new Exception("Достигнуто предвиденное исключение. Для коррекции необходимо обратиться к автору программы"); } // Замещение операции и операнда ссылкой на результат операции links.RemoveAt(maxIndex); links.RemoveAt(maxIndex); links.Insert(maxIndex, -chain.Count); break; // Обработка бинарных операций case Lexeme.LexemeTypes.Plus: case Lexeme.LexemeTypes.Minus: case Lexeme.LexemeTypes.Multiplication: case Lexeme.LexemeTypes.Division: case Lexeme.LexemeTypes.Exponentiation: if (links[maxIndex - 1] >= 0) { // По факту if (links[maxIndex + 1] >= 0) { chain.Add(new EvaluationChainElement(ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex - 1] % 1000], ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000], ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex + 1] % 1000])); } // Со вторым операндом-ссылкой else { chain.Add(new EvaluationChainElement(ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex - 1] % 1000], ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000], (uint)(-links[maxIndex + 1] - 1))); } } else { // С первым операндом-ссылкой if (links[maxIndex + 1] >= 0) { chain.Add(new EvaluationChainElement((uint)(-links[maxIndex - 1] - 1), ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000], ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex + 1] % 1000])); } // С обоими операндами-ссылками else { chain.Add(new EvaluationChainElement((uint)(-links[maxIndex - 1] - 1), ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000], (uint)(-links[maxIndex + 1] - 1))); } } // То же самое if (!chain[chain.Count - 1].IsInited) { throw new Exception("Достигнуто предвиденное исключение. Для коррекции необходимо обратиться к автору программы"); } // Замещение операции и операнда ссылкой на результат операции links.RemoveAt(maxIndex - 1); links.RemoveAt(maxIndex - 1); links.RemoveAt(maxIndex - 1); links.Insert(maxIndex - 1, -chain.Count); break; // Остальных лексем здесь быть не должно default: throw new Exception("Достигнуто предвиденное исключение. Для коррекции необходимо обратиться к автору программы"); } } // Если массив шагов пуст, то операций в выражении не было if (chain.Count == 0) { // Необходимо для фильтрации скобок chain.Add(new EvaluationChainElement(ExpressionLexemesExtractor.ExtractedLexemes[links[maxIndex] % 1000])); if (!chain[chain.Count - 1].IsInited) { throw new Exception("Достигнуто предвиденное исключение. Для коррекции необходимо обратиться к автору программы"); } } // Завершено isInited = true; }
// Обновление статуса проверки формулы и добавление кривой private void AddButton_Click(object sender, EventArgs e) { // Блокировка контролов FormulaBox.ReadOnly = true; AddButton.Enabled = DeleteButton.Enabled = false; ApplyButton.Enabled = AbortButton.Enabled = false; // Контроль порядка лексем в выражении LexemesExtractor le = new LexemesExtractor(FormulaBox.Text); switch (le.FollowingStatus) { case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedConstant: InfoLabel.Text = string.Format(Localization.GetText("MisplacedConstantError", language), le.LastLexeme); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedDivisionOperator: InfoLabel.Text = Localization.GetText("MisplacedDivisionOperatorError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedExponentiationOperator: InfoLabel.Text = Localization.GetText("MisplacedExponentiationOperatorError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedFunctionCall: InfoLabel.Text = string.Format(Localization.GetText("MisplacedFunctionCallError", language), le.LastLexeme); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedLeftParenthesis: InfoLabel.Text = Localization.GetText("MisplacedLeftParenthesisError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedMinusOperator: InfoLabel.Text = Localization.GetText("MisplacedMinusOperatorError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedMultiplicationOperator: InfoLabel.Text = Localization.GetText("MisplacedMultiplicationOperatorError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedNumber: InfoLabel.Text = string.Format(Localization.GetText("MisplacedNumberError", language), le.LastLexeme); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedPlusOperator: InfoLabel.Text = Localization.GetText("MisplacedPlusOperatorError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedRightParenthesis: InfoLabel.Text = Localization.GetText("MisplacedRightParenthesisError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.MisplacedVariable: InfoLabel.Text = Localization.GetText("MisplacedVariableError", language); break; case LexemesFollowingMatrix.LexemesFollowingStatuses.UnknownLexeme: InfoLabel.Text = string.Format(Localization.GetText("UnknownLexemeError", language), le.LastLexeme); break; } if (le.FollowingStatus != LexemesFollowingMatrix.LexemesFollowingStatuses.Ok) { InfoLabel.ForeColor = Color.FromArgb(128, 32, 0); FormulaBox.ReadOnly = false; AddButton.Enabled = (CurvesList.Items.Count < DiagramData.MaxLines); DeleteButton.Enabled = ApplyButton.Enabled = (CurvesList.Items.Count > 0); AbortButton.Enabled = true; return; } // Первичная обработка выражения switch (le.ExpressionStatus) { case LexemesExtractor.ExpressionStatuses.ExpressionIsEmpty: InfoLabel.Text = Localization.GetText("ExpressionIsEmptyError", language); break; case LexemesExtractor.ExpressionStatuses.IncorrectExpressionEnd: InfoLabel.Text = string.Format(Localization.GetText("IncorrectExpressionEndError", language), le.LastLexeme); break; case LexemesExtractor.ExpressionStatuses.IncorrectExpressionStart: InfoLabel.Text = string.Format(Localization.GetText("IncorrectExpressionStartError", language), le.LastLexeme); break; case LexemesExtractor.ExpressionStatuses.LeftParenthesisWasNotClosed: InfoLabel.Text = Localization.GetText("LeftParenthesisWasNotClosedError", language); break; case LexemesExtractor.ExpressionStatuses.MisplacedRightParenthesis: InfoLabel.Text = Localization.GetText("UnexpectedRightParenthesisError", language); break; } if (le.ExpressionStatus != LexemesExtractor.ExpressionStatuses.Ok) { InfoLabel.ForeColor = Color.FromArgb(128, 0, 0); FormulaBox.ReadOnly = false; AddButton.Enabled = (CurvesList.Items.Count < DiagramData.MaxLines); DeleteButton.Enabled = ApplyButton.Enabled = (CurvesList.Items.Count > 0); AbortButton.Enabled = true; return; } // Проверка успешно завершена InfoLabel.ForeColor = Color.FromArgb(0, 128, 0); InfoLabel.Text = Localization.GetText("NoErrors", language) + "\nf(x) = "; string formula = ""; for (int i = 0; i < le.ExtractedLexemes.Count; i++) { formula += le.ExtractedLexemes[i].LexemeValue; InfoLabel.Text += le.ExtractedLexemes[i].LexemeValue; } // Добавление кривой в список CurvesList.Items.Add(formula); // Разблокировка контролов FormulaBox.ReadOnly = false; AddButton.Enabled = (CurvesList.Items.Count < DiagramData.MaxLines); DeleteButton.Enabled = ApplyButton.Enabled = true; AbortButton.Enabled = true; }