// verejne metody /// <summary> /// Konstruktor objektu /// </summary> /// <description> /// Inicializace objektu /// </description> /// <param name="expr"> /// matematický výraz, který je nastaven do vlastnosti <see cref="Expression" />, /// a jeho vyhodnocení je v <see cref="Value" /> /// </param> public Calculation(string expr) { d_value = double.NaN; t_calcError = CalcErrorType.None; o_mathLib = new CalcMath(); Expression = expr; }
/// <summary> /// Calculation error event handler /// </summary> /// <param name="errorType">Type of error</param> /// <param name="errorCode">Unique error identifier code</param> /// <param name="context">Error context</param> /// <param name="message">Error message</param> /// <param name="expression">Expression which caused the error, limited to the first 1024 characters</param> /// <param name="options">Error options</param> /// <param name="status">Return status</param> private void CalculatingError(CalcErrorType errorType, uint errorCode, string context, string message, string expression, uint options, ref CalcStatus status) { MessageBoxButton button = (errorType == CalcErrorType.ErrorExpression) ? MessageBoxButton.OKCancel : MessageBoxButton.OK; MessageBoxResult result = MessageBoxResult.OK; //Dispatch UI commands to the UI thread Dispatcher.Invoke(() => { result = MessageBox.Show( this, $"An error has occurred whilst calculating\n\ncontext: {context}\nExpression: {expression}\n\n{message}\n", "Calculation Error", button, MessageBoxImage.Error); }); if (errorType == CalcErrorType.ErrorExpression && result != MessageBoxResult.OK) { status = CalcStatus.Aborted; //status = CalcStatus.Interrupted; //Interrupt to show the error in the output and keep the current variables } }
private double EvaluateExpr(string expr) { t_calcError = CalcErrorType.None; Char[] workStr = PreprocessExpr(expr).ToArray(); // zavorkujeme aby se spravne zpetne vyhodnotil cely vyraz // zasobniky Stack <double> operandStack = new Stack <double>(); Stack <char> operatorStack = new Stack <char>(); // zpracovavame vyraz po znacich for (int i = 0; i < workStr.Length; i++) { // Zpracovani operandu if (Char.IsDigit(workStr[i])) // pokud je cislice { double valtmp = double.NaN; t_calcError = ProcessOperand(workStr, ref i, out valtmp); if (t_calcError == CalcErrorType.None) { operandStack.Push(valtmp); } else { return(valtmp); } continue; // operand je zpracovan a index posunut na jeho konec ... opakujeme cyklus. } // Zpracovani operatoru if ("!L^@%*/-+".Contains(workStr[i])) { // zkontrolujeme, jestli se jedna o platny unarni operator ... pokud nebude vyhodnocen jako unarni, tak metoda vraci true if (!ProcessOperator(ref workStr, i)) { t_calcError = CalcErrorType.ExprFormatError; return(double.NaN); } // pokud je operator mensi priority nez posledni operator na zasobniku, provedem predchozi operaci while ( operatorStack.Count > 0 && GetOperatorPriority(operatorStack.Peek()) >= GetOperatorPriority(workStr[i]) ) { // Pokusime se provest operaci na zasobnicich t_calcError = PopOperation(operatorStack, operandStack); if (t_calcError != CalcErrorType.None) { return(operandStack.Pop()); // vysledek (inf/NaN) je na vrcholu } } // ulozime aktualni operator operatorStack.Push(workStr[i]); continue; } // zavorky oteviraci se ukladaji pro skonceni vyhodnoceni podvyrazu else if (workStr[i] == '(') { operatorStack.Push(workStr[i]); } // uzaviraci zavorka znamena vyhodnot vsechno zpetne az do oteviraci zavorky else if (workStr[i] == ')') { if (operatorStack.Count < 1) { t_calcError = CalcErrorType.ExprFormatError; return(double.NaN); } while (operatorStack.Peek() != '(') { // Pokusime se provest operaci na zasobnicich t_calcError = PopOperation(operatorStack, operandStack); if (t_calcError != CalcErrorType.None) { return(operandStack.Pop()); // vysledek (inf/NaN) je na vrcholu } } operatorStack.Pop(); } else // neznamy znak { t_calcError = CalcErrorType.ExprFormatError; return(double.NaN); } } // na zasobniku by mela zustat jenom jedna hodnota if (operandStack.Count != 1) { t_calcError = CalcErrorType.ExprFormatError; return(double.NaN); } return(operandStack.Pop());//double.NaN; }