/// <summary> /// 单步计算 /// </summary> /// <returns>单步计算结果</returns> public CalResult CalculateOneStep() { CalResult result = null; int currentPos = -1; try { #region 优先级列表为空的情况 //优先级列表不存在的情况 if (levelList.Count == 0) { #region 完成计算后(优先级列表为空,无需计算),删除逗号 //扫描运算因子列表,删除逗号 for (int i = 0; i < valList.Count; i++) { //找到逗号 if (valList[i].OpeType == OpeType.Separator) { this.valList.RemoveAt(i); //调整i i--; } } #endregion #region 完成计算后(优先级列表为空,无需计算),删除括号 //扫描运算因子列表,删除括号 for (int i = 0; i < valList.Count; i++) { //找到括号 if (valList[i].OpeType == OpeType.leftParenthesis || valList[i].OpeType == OpeType.rightParenthesis) { this.valList.RemoveAt(i); //调整i i--; } } #endregion if (valList.Count == 1)//一个计算结果 { //该运算因子是数字 if (valList[0].type == ValType.Number) { double r; //如果无法转换成double值 if (!double.TryParse(valList[0].num.stringValue, out r)) { throw new Exception("请输入正确的表达式"); } } result = new CalResult(); result.numList.Add(valList[0].num); } else//多个计算结果 { result = new CalResult(); for (int i = 0; i < valList.Count; i++) { //该运算因子是数字 if (valList[i].type == ValType.Number) { double r; //如果无法转换成double值 if (!double.TryParse(valList[i].num.stringValue, out r)) { throw new Exception("请输入正确的表达式"); } } result.numList.Add(valList[i].num); } } return result; } #endregion #region 核心算法,对于当前优先级,扫描运算因子列表并计算 if (levelList.Count != 0)//优先级列表不为空 { #region 处理当前优先级 //对于当前优先级,逐个扫描运算因子,处理具有该优先级的运算 for (int i = 0; i < valList.Count; i++) { //找到具有该优先级的运算符 if (valList[i].type == ValType.Operator && valList[i].level == levelList[0])//该运算因子的优先级等于当前优先级 { bool isSign = false;//Sign为true表示当前运算因子是正负号 currentPos = valList[i].primalPos;//记录当前运算因子在列表中的原始位置 //参数列表 List<CalNum> numList = new List<CalNum>(); //临时计算结果 CalNum num; switch (valList[i].OpeType)//i表示该运算因子的位置 { #region case OpeType.PlusOrMinus: case OpeType.PlusOrMinus: //若该运算符前面没有运算因子 //或前一个运算因子是运算符,则按正负号计算 if (i == 0 || (i - 1 >= 0 && valList[i - 1].type == ValType.Operator)) { isSign = true;//是正负号 //获取该运算符的参数 if (i + 1 < valList.Count && valList[i + 1].type == ValType.Number) { //注意,下面第一句不可省略 numList = new List<CalNum>(); numList.Add(valList[i + 1].num); } //计算 num = CalOpeList.Calculate(valList[i].ope, numList); //更新运算因子列表 ReplaceVal(num, 2, i); //i无需调整 } else//若前一个运算因子是操作数,则按加减号计算 { //获取该运算符的参数 if (valList[i - 1].type == ValType.Number && i + 1 < valList.Count && valList[i + 1].type == ValType.Number) { //注意,下面第一句不可省略 numList = new List<CalNum>(); numList.Add(valList[i - 1].num); numList.Add(valList[i + 1].num); } //计算 num = CalOpeList.Calculate(valList[i].ope, numList); //更新运算因子列表 ReplaceVal(num, 3, i - 1); //调整i i--; } break; #endregion #region case OpeType.bothSides: case OpeType.bothSides: //获取该运算符的参数 if (i >= 1 && valList[i - 1].type == ValType.Number && i + 1 < valList.Count && valList[i + 1].type == ValType.Number) { //注意,下面第一句不可省略 numList = new List<CalNum>(); numList.Add(valList[i - 1].num); numList.Add(valList[i + 1].num); } //计算 num = CalOpeList.Calculate(valList[i].ope, numList); //更新运算因子列表 ReplaceVal(num, 3, i - 1); //调整i i--; break; #endregion #region case OpeType.left: case OpeType.left: //获取该运算符的参数 if (i >= 1 && valList[i - 1].type == ValType.Number) { //注意,下面第一句不可省略 numList = new List<CalNum>(); numList.Add(valList[i - 1].num); } //计算 num = CalOpeList.Calculate(valList[i].ope, numList); //更新运算因子列表 ReplaceVal(num, 2, i - 1); //调整i i--; break; #endregion #region case OpeType.noParameter: case OpeType.noParameter: //注意,下面第一句不可省略 numList = new List<CalNum>(); //计算 num = CalOpeList.Calculate(valList[i].ope, numList); //更新运算因子列表 ReplaceVal(num, 1, i); break; #endregion #region case OpeType.right: case OpeType.right: #region 该运算符只有一个参数,且它的右边是常数 if (i + 1 < valList.Count && valList[i].ParameterNumber == 1 && valList[i + 1].type == ValType.Number) { //获取该运算符的参数 //注意,下面第一句不可省略 numList = new List<CalNum>(); numList.Add(valList[i + 1].num); //计算 num = CalOpeList.Calculate(valList[i].ope, numList); //更新运算因子列表 ReplaceVal(num, 2, i); } #endregion #region 该运算符不是只有一个参数,或者它的右边不是常数 else { //计算参数个数 int count = 0; int k = i + 1; //从运算符后面开始检测 //如果是左括号、分隔符或数字,则执行while中语句 while (k < valList.Count && (valList[k].type == ValType.Number || valList[k].OpeType == OpeType.Separator || valList[k].OpeType == OpeType.leftParenthesis)) { //如果是数字,参数个数加1 if (valList[k].type == ValType.Number) { count++; } k++; } //注意,下面第一句不可省略 numList = new List<CalNum>(); //从该运算符后面,逐个扫描,获取该运算符的参数 //j表示已读取的参数个数 //m表示检测位置增量 int m = 0; for (int j = 0; j < count; ) { //如果找到数字,存为参数 if (valList[i + j + m + 1].type == ValType.Number) { numList.Add(valList[i + j + m + 1].num); j++; } //如果是分隔符或左括号,检测位置增量加1,表示跳过该运算因子,继续检测 else if (valList[i + j + m + 1].OpeType == OpeType.Separator || valList[i + j + m + 1].OpeType == OpeType.leftParenthesis) { m++; } } //计算 num = CalOpeList.Calculate(valList[i].ope, numList); //更新运算因子列表,count+m+2中的2表示运算符本身和右括号 ReplaceVal(num, count + m + 2, i); } #endregion break; #endregion }//end switch if (!isSign)//如果不是正负号 { break;//退出for循环 } } } #endregion #region 删除处理完的优先级 bool levelExists = false;//是否存在具有该优先级的运算符 //逐个扫描运算因子,判断是否仍存在具有该优先级的运算符 for (int i = 0; i < valList.Count; i++) { if (levelList[0] == valList[i].level)//存在 { levelExists = true; } } if (!levelExists)//该优先级已处理完则删除它 { levelList.RemoveAt(0); } #endregion } #endregion #region 处理计算结果 //处理计算结果 if (levelList.Count == 0)//全部优先级已经处理完毕 { #region 完成计算后,删除逗号 //扫描运算因子列表,删除逗号 for (int i = 0; i < valList.Count; i++) { //找到逗号 if (valList[i].OpeType == OpeType.Separator) { this.valList.RemoveAt(i); //调整i i--; } } #endregion #region 完成计算后,删除括号 //扫描运算因子列表,删除括号 for (int i = 0; i < valList.Count; i++) { //找到括号 if (valList[i].OpeType == OpeType.leftParenthesis || valList[i].OpeType == OpeType.rightParenthesis) { this.valList.RemoveAt(i); //调整i i--; } } #endregion if (valList.Count == 1)//一个计算结果 { result = new CalResult(); result.numList.Add(valList[0].num); } else//多个计算结果 { result = new CalResult(); for (int i = 0; i < valList.Count; i++) { result.numList.Add(valList[i].num); } } } else//全部优先级未处理完 { result = new CalResult(); result.numList.Add(new CalNum(BackToStrExp()));//剩下的运算因子列表转换成string后作为计算结果返回 } #endregion } catch (Exception ex) { if (currentPos != -1) { MakeException(currentPos, ex); } else { throw new Exception(ex.Message); } } return result; }
/// <summary> /// 等于 /// </summary> private void btnEqual_Click(object sender, EventArgs e) { //判断程序能否继续使用 if (!Common.IsProgramPassValidate()) { try { RegisterForm regForm = new RegisterForm(); regForm.ShowDialog(this); return; } catch { return; } } try { if (this.语音ToolStripMenuItem1.Checked) { //中止之前的计算结果发音 if (this.speechResultThread != null) { this.speechResultThread.Abort(); this.speechResultThread = null; } } if (txtExp.Text.IndexOf("=") != -1)//存储变量 { memoryVars(); } else//计算 { result = Calculate();//计算 ANS = result.GeneralResultToShow;//保存计算结果 txtResult.Text = ANS;//显示计算结果 //计算结果发音 if (this.语音ToolStripMenuItem1.Checked) { //起动线程发音 speechResultThread = new System.Threading.Thread(new System.Threading.ThreadStart(SpeechResult)); speechResultThread.Start(); } } txtExp.Focus(); txtExp.SelectionStart = txtExp.Text.Length; isScientificShow = false; //记录表达式 MemoryExpr_Cal(); } catch (Exception ex) { //计算结果框中显示出错信息 ShowException(ex); } }
/// <summary> /// 计算表达式 /// </summary> private CalResult Calculate() { CalValList valList = null; //记录表达式 memoryExp = txtExp.Text; //删除注释 txtExp.Text = Common.DeleteAnnotate(txtExp.Text, out hasAnnotate); //生成运算因子列表 valList = new CalValList(txtExp.Text); //重新显示表达式 if (hasAnnotate)//有注释 { txtExp.Text = memoryExp; } else//没有注释 { txtExp.Text = valList.nomalStringExpression; } CalResult result = null; if (this.单步计算ToolStripMenuItem.Checked)//单步计算 { completeSteps++; for (int i = 0; i < completeSteps; i++) { //优先级列表为空的情况 if (valList.levelList.Count == 0) { result = valList.CalculateOneStep(); } if (valList.levelList.Count > 0)//如果优先级尚未处理完毕 { result = valList.CalculateOneStep(); } } } else//一次性计算最终结果 { result = valList.Calculate();//计算 } return result; }
/// <summary> /// txtExp文本框事件 /// </summary> private void txtExp_TextChanged(object sender, EventArgs e) { try { _selectionStartPos = txtExp.SelectionStart; //如果调用了Common.SetWrongOpeColor将不再调用Common.SetColor if (!Common._lock) { Common.SetColor(txtExp.Text, txtExp); } txtExp.SelectionStart = _selectionStartPos; //清空计算结果 if (txtExp.Text.Trim() == "") { result = null; } //发音 if (this.语音ToolStripMenuItem1.Checked) { //中止计算结果发音 if (this.speechResultThread != null) { this.speechResultThread.Abort(); this.speechResultThread = null; } if (this.isKeyDown) { string tag = txtExp.Text[txtExp.SelectionStart - 1].ToString(); switch (tag) { case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": tag = "_" + tag; break; case ".": tag = "点"; break; case "+": tag = "加上"; break; case "-": //是负号 if (Common.isSubtractive(txtExp.Text, tag, txtExp.SelectionStart)) { tag = "负"; } else { tag = "减去"; } break; case "*": tag = "乘以"; break; case "/": tag = "除以"; break; } Common.Speech(tag); this.isKeyDown = false; } } } catch { } }