关于表达式中除数为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(); }
图例:
阅读全文
0 0
- 关于表达式中除数为0的容错机制的处理
- Oracle 除数为0的处理(decode)
- JAVA中除数为0的问题
- sql server中除数为零的处理技巧
- 在vc6.0中除数为零的验证
- Java中除数为0时计算报错的问题
- SQL 中除数为零的解决方法
- oracle数据同比的时候除数为0该怎么处理
- java中除数是0的问题
- sql中除数为零和null的判断
- oracle 除数为0,默认为0的自定义函数
- 在sql中遇到除数为0的错误时候的解决办法
- JSON的容错机制
- MapReduce的容错机制
- hadoop的容错机制
- MapReduce的容错机制
- MapReduce的容错机制
- SSRS----添加计算字段,除数若为0的解决办法
- Wins系统带选项复制命令robocopy的操作方法介绍
- c# 发送qq邮箱本地正常 布置到服务器上后出现的异常
- 求最长上升子序列
- 【分析】Ceph系统架构
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛
- 关于表达式中除数为0的容错机制的处理
- 把数组排成最小的数
- 剑指Offer----跳台阶
- Js-web-API(一)
- 实现自定义标签
- poll服务器
- 面向对象(上)
- leetcode 72. Edit Distance
- 20170710Windows11_2_事件内核对象