关于表达式中除数为0的容错机制的处理

来源:互联网 发布:angularjs.js 2.0下载 编辑:程序博客网 时间:2024/05/16 08:50

说明:对于一个表达式(比如1+2/(A-B)),如果A-B为0,有时我们想这个表达式返回1,而不是0或者抛出异常。也就是局部的除数异常是允许的。这个时候就需要对公式做容错处理。

下面是用C#的处理过程,如有错误,欢迎指正

/// <summary>    /// 公式容错    /// 在执行公式时,会有除数为0的情况,此时不应该报错,只是包含除数为0的表达式计算结果为0,整个表达式继续执行    /// 如1+(2/(4-8/(1+1)))  执行结果应该是1 而不应该报错    /// 方法:    /// 1:将原表达式转换为后缀表达式    /// 2:再将后缀表达式转换为容错之后的中缀表达式    /// 3:栈顶元素即为结果    /// </summary>    public class FormulasConvert {        //存原始后缀表达式        Stack<char> _suffixStack = new Stack<char>();        /// <summary>        /// 后缀表达式结果        /// </summary>        public string _suffixFormula = string.Empty;        //存容错后中缀表达式        Stack<string> _infixingStack = new Stack<string>();        /// <summary>        /// 容错后中缀表达式结果        /// </summary>        public string _infixingFormula = string.Empty;        /// <summary>        /// 原始公式        /// </summary>        private string _inputFormula = string.Empty;        /// <summary>        /// 用字符转换之后的原始公式        /// 10+10==》A+B        /// </summary>        private string _newFormula = string.Empty;        //操作符        private string _operator = "+-*/()";        /// <summary>        /// 原公式:100+2/300        /// 对应:        /// A:100  B:2 C:300        /// 最终        /// A+B/C        /// </summary>        Dictionary<string, string> _dicCompary = new Dictionary<string, string>();        public FormulasConvert(string inputFormula) {            this._inputFormula = inputFormula;        }        /// <summary>        /// 将原始表达式转换成后缀表达式        /// </summary>        /// <param name="inputString">原中缀表达式</param>        /// <returns></returns>        public string ConvertToSuffix() {            OperatorFormula();            for (int i = 0; i < _newFormula.Length; i++) {                char ch = _newFormula[i];                if (!IsOperator(ch)) {                    _suffixFormula += ch;                } else if (ch == '(')                    _suffixStack.Push(ch);                else if (ch == ')') {                    while (_suffixStack.Peek() != '(')                        _suffixFormula += _suffixStack.Pop();                    _suffixStack.Pop();                } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {                    if (_suffixStack.Count == 0)                        _suffixStack.Push(ch);                    else if (_suffixStack.Peek() == '(')                        _suffixStack.Push(ch);                    else if (CompareOperate(ch, _suffixStack.Peek()) == 1)                        _suffixStack.Push(ch);                    else if (CompareOperate(ch, _suffixStack.Peek()) == 0) {                        _suffixFormula += _suffixStack.Pop();                        _suffixStack.Push(ch);                    } else if (CompareOperate(ch, _suffixStack.Peek()) == -1) {                        int com = -1;                        while (com == -1 || com == 0) {                            _suffixFormula += _suffixStack.Pop();                            if (_suffixStack.Count != 0)                                com = CompareOperate(ch, _suffixStack.Peek());                            else                                break;                        }                        _suffixStack.Push(ch);                    }                }            }            string tmpStr = string.Empty;            for (int i = 0; i < _suffixStack.Count + 1; i++) {                if (_suffixStack.Count > 0) {                    tmpStr += _suffixStack.Peek().ToString();                    _suffixStack.Pop();                }            }            _suffixFormula = _suffixFormula + tmpStr;            return GetFormulaResult(_suffixFormula);        }        private int CompareOperate(char ch, char stackCh) {            if (ch == stackCh)                return 0;            else if ((ch == '+' && stackCh == '-') || (ch == '-' && stackCh == '+'))//表示等于                return 0;            else if ((ch == '*' && stackCh == '/') || (ch == '/' && stackCh == '*'))                return 0;            else if ((ch == '+' || ch == '-') && (stackCh == '*' || stackCh == '/'))//表示小于                return -1;            else if ((ch == '*' || ch == '/') && (stackCh == '+' || stackCh == '-'))//返回1 表示输入运算符的优先级大于栈顶运算符                return 1;            else                return -2;        }        /// <summary>        /// 将后缀表达式生成中缀表达式(未容错)        /// </summary>        /// <returns></returns>        public string ConvertToInfixing() {            if (string.IsNullOrEmpty(this._inputFormula))                return string.Empty;            ConvertToSuffix();            if (string.IsNullOrEmpty(this._suffixFormula))                return string.Empty;            for (int i = 0; i < _suffixFormula.Length; i++) {                char ch = _suffixFormula[i];                if (!IsOperator(ch)) { //操作数入栈                    _infixingStack.Push(ch.ToString());                } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {                    string tmp1 = _infixingStack.Pop();                    string tmp2 = _infixingStack.Pop();                    string tmp = string.Empty;                    tmp = "(" + tmp2;                    tmp += ch;                    tmp += tmp1 + ")";                    _infixingStack.Push(tmp);                }            }            return GetFormulaResult(_infixingStack.Peek());        }        /// <summary>        /// 将后缀表达式生成中缀表达式(容错,替换除数为0)        /// 返回容错之后的新中缀表达式        /// </summary>        /// <param name="inputString"></param>        /// <returns></returns>        public string Convert() {            if (string.IsNullOrEmpty(this._inputFormula))                return string.Empty;            ConvertToSuffix();            if (string.IsNullOrEmpty(this._suffixFormula))                return string.Empty;            for (int i = 0; i < _suffixFormula.Length; i++) {                char ch = _suffixFormula[i];                if (!IsOperator(ch)) { //操作数入栈                    _infixingStack.Push(ch.ToString());                } else if (ch == '+' || ch == '-' || ch == '*') {                    string tmp1 = _infixingStack.Pop();                    string tmp2 = _infixingStack.Pop();                    string tmp = string.Empty;                    tmp = "(" + tmp2;                    tmp += ch;                    tmp += tmp1 + ")";                    _infixingStack.Push(tmp);                } else if (ch == '/') {                    //(A if(Ture) else B)                    string tmp1 = _infixingStack.Pop();                    string tmp2 = _infixingStack.Pop();                    string tmp = string.Empty;                    tmp = "(0 if(" + tmp1 + "==0) else (" + tmp2 + "/" + tmp1 + "))";                    _infixingStack.Push(tmp);                }            }            return GetFormulaResult(_infixingStack.Peek());        }        /// <summary>        /// 处理原始表达式为原运算符        /// 最终变成A+B/C这种模式        /// </summary>        private void OperatorFormula() {            if (string.IsNullOrEmpty(this._inputFormula))                return;            //26个字母应该够用了,一个公式有26个运算项已经够多了            char start = 'A';            string tmpData = string.Empty;            for (int i = 0; i < this._inputFormula.Length; i++) {                char ch = _inputFormula[i];                if (IsOperator(ch)) {                    if (!string.IsNullOrEmpty(tmpData.Trim())) {                        this._dicCompary.Add(start.ToString(), tmpData);                        _newFormula += start.ToString();                        start = (char)((int)start + 1);                        tmpData = string.Empty;                    } else {                        tmpData = string.Empty;  //空格不处理                    }                    _newFormula += ch.ToString();                } else {                    tmpData += _inputFormula[i].ToString();                }            }            if (!string.IsNullOrEmpty(tmpData.Trim())) {                _dicCompary.Add(start.ToString(), tmpData);                _newFormula += start.ToString();  //加上最后一个操作数            }        }        /// <summary>        /// 根据_newFormula与_dicCompary重新组织成公式        /// </summary>        /// <returns></returns>        private string GetFormulaResult(string formulas) {            if (string.IsNullOrEmpty(formulas))                return string.Empty;            string newFormulas = string.Empty;            for (int i = 0; i < formulas.Length; i++) {                string key = formulas[i].ToString();                if (_dicCompary.ContainsKey(key)) {                    newFormulas += _dicCompary[key];                } else {                    newFormulas += key;                }            }            return newFormulas;        }        //判断是否是操作符,目前操作符为+-*/()        private bool IsOperator(char c) {            return _operator.Contains(c.ToString());        }    }
测试:

private void button2_Click(object sender, EventArgs e) {            FormulasConvert convert = new FormulasConvert(this.label2.Text);            richTextBox2.Text = convert.ConvertToSuffix();        }        private void button3_Click(object sender, EventArgs e) {            FormulasConvert convert = new FormulasConvert(this.label2.Text);            richTextBox3.Text = convert.Convert();        }

图例:



原创粉丝点击