用Visual C# 实现四则混合运算

2016-02-19 15:53 17 1 收藏

图老师设计创意栏目是一个分享最好最实用的教程的社区,我们拥有最用心的各种教程,今天就给大家分享用Visual C# 实现四则混合运算的教程,热爱PS的朋友们快点看过来吧!

【 tulaoshi.com - 编程语言 】

  本文是介绍使用Visual C#实现自动计算四则混合运算的一种方法,在.NET1.1框架中,还没有包含全现成的类,不过,现在经过我们下文的介绍,大家完全可以自己写一个,作用嘛,没什么,就是熟悉一下栈的用法,或者家里有上小学的,可以写一个程序给孩子练习一下四则混合运算也行,哈哈,废话不多说了,讲正题吧。

  出一个典型的算术题: (6+2*5)/4

  从题中,我们首先算 2*5=10 接下来算 6+10=16 最后算 16/4 =4 所以,结果是4

  计算机怎么算?还好前辈给我们列出来一堆的算法,我们随便选一个就可以了。

  第一种算法

  使用栈来解决,意思就是把不优极最低的压到栈的最下面去,按照先进后出的原则,那么最优先级最低的就是最后计算了。

  计算过程:

  我们建立两个栈,一个是数据栈,一个是计算符号栈,以(6+2*5)/4为例子,看看倒底是怎么计算的。

  假设:

  1)优先级

  符号之间的优先级如下:

  ( ) -1

  +,- 0

  *,/ 1

  数值越大,则越优先,同级别的比较时 先出现的优先。

  2)将(,)设为特殊运算符,即单目运算,两邻两个运算符则可对消。

  3) 计算条件

  (1) 当前运算符不等于(特殊结束符)

  (2) 运算符栈里的运行算个数=1时

  (3) 出栈口的运算符优先级高于将要入栈的运算符时或者两者可对消时。

  计算时,则将符号出栈参与计算,数值栈的出栈口前两位元素出栈参与计算,计算结果值向数值栈压栈,并进行递归此操作。

  图1:

  1) ( 压入符号栈 2 ) 6压入数值栈

  3) (与+比较优先级,认为(比+优先级低,则不满足计算条件,将+压入符号栈.

  图2:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  1) 将2 压入数值栈。

  2) 将*与+比较优先级,算得+优先级低于*,则不满足计算条件,将*压入符号栈。

  图3:

  1) 将 5压入数植栈。 2) 将*与)比较优先级,得出*比)优先级要高。进行计算,将*出栈、5、2出栈,参与计算

  图4:

  1) 将 2*5 =10的结果压入数值栈。

  2) (递归)比较 +与)优先级,得出+比)优先级要高。再进行计算,将+出栈、10、6出栈,参与计算。

  图 5:

  1) 将 6+10 =16的结果压入数值栈。

  2) (递归)比较 )与(优先级,得出两者可以对消,将(符号出栈,与)对消,继续取下一个符号。

  图6:

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/bianchengyuyan/)

  1) 将/入符号栈。

  2)将4入数值栈。

  3) 发现算式结束符,则进行计算, 将 /、4’、16出栈,参与计算。

  图7:

  1) 将计算结果压入数值栈。

  成功了! 辛苦的计算工作终于干完了,看起来比人脑计算复杂多了:)

  第二种算法

  第二种方法,我们简单的提一下,在这里不作详细过程的叙述。第二种,就是使用树的方式,将一个算式组织成一定规律的树,之后,再进行遍历计算即得得到结果。还是以上面的算式作例子,最终形成的树的样式:(注意()这个符号要特殊处理)

  图8:

  使用树的深度遍历即可算出最终的结果。

  程序实现

  本文,给出使用栈处理四则运算的C#实现方法,如下:

  

CalUtility.csusing System;namespace Calculate{ /// summary /// CalUtility 的摘要说明。 /// 读算式辅助工具 /// /summary public class CalUtility {  System.Text.StringBuilder StrB;  private int iCurr=0;  private int iCount=0;  /// summary  /// 构造方法  /// /summary  public CalUtility(string calStr)  {   StrB = new System.Text.StringBuilder(calStr.Trim());   iCount = System.Text.Encoding.Default.GetByteCount(calStr.Trim());  }  /// summary  /// 取段,自动分析数值或计算符  /// /summary  /// returns/returns  public string getItem()  {   //结束了   if(iCurr==iCount)    return "";   char ChTmp = StrB[iCurr];   bool b=IsNum(ChTmp);   if(!b)   {    iCurr++;    return ChTmp.ToString();   }   string strTmp="";   while(IsNum(ChTmp)==b && iCurriCount)   {    ChTmp = StrB[iCurr];    if(IsNum(ChTmp)==b)     strTmp +=ChTmp;    else     break;    iCurr++;   }   return strTmp;  }  /// summary  /// 是否是数字  /// /summary  /// param name="c"内容/param  /// returns/returns  public bool IsNum(char c)  {   if((c=’0’ && c=’9’)|| c==’.’)   {    return true;   }   else   {    return false;   }  }  /// summary  /// 是否是数字  /// /summary  /// param name="c"内容/param  /// returns/returns  public bool IsNum(string c)  {   if(c.Equals(""))    return false;   if((c[0]=’0’ && c[0]=’9’)|| c[0]==’.’)   {    return true;   }   else   {    return false;   }  }  /// summary  /// 比较str1和str2两个运算符的优先级,ture表示str1高于str2,false表示str1低于str2  /// /summary  /// param name="str1"计算符1/param  /// param name="str2"计算符2/param  /// returns/returns  public bool Compare(string str1,string str2)  {   return getPriority(str1)=getPriority(str2);  }  /// summary  /// 取得计算符号的优先级  /// /summary  /// param name="str"计算符/param  /// returns/returns  public int getPriority(string str)  {   if(str.Equals(""))   {    return -1;   }   if(str.Equals("("))   {    return 0;   }   if(str.Equals("+")||str.Equals("-"))   {    return 1;   }   if(str.Equals("*")||str.Equals("/"))   {    return 2;   }   if(str.Equals(")"))   {    return 0;   }   return 0;  } }}IOper.csusing System;namespace Calculate{ /// summary /// IOper 的摘要说明。 /// 计算符接口 /// /summary public interface IOper {  /// summary  /// 计算符计算接口计算方法  /// /summary  /// param name="o1"参数1/param  /// param name="o2"参数2/param  /// returns/returns  object Oper(object o1,object o2); }}Opers.csusing System;namespace Calculate{ /// summary /// Opers 的摘要说明。 /// 各类计算符的接口实现,加减乘除 /// /summary public class OperAdd:IOper {  public OperAdd()  {   //   // TODO: 在此处添加构造函数逻辑   //  }  #region IOper 成员 public object Oper(object o1, object o2) {  Decimal d1 = Decimal.Parse(o1.ToString());  Decimal d2 = Decimal.Parse(o2.ToString());  return d1+d2; } #endregion}public class OperDec:IOper{ public OperDec() {  //  // TODO: 在此处添加构造函数逻辑  // } #region IOper 成员 public object Oper(object o1, object o2) {  Decimal d1 = Decimal.Parse(o1.ToString());  Decimal d2 = Decimal.Parse(o2.ToString());  return d1-d2; } #endregion}public class OperRide:IOper{ public OperRide() {  //  // TODO: 在此处添加构造函数逻辑  // } #region IOper 成员 public object Oper(object o1, object o2) {  Decimal d1 = Decimal.Parse(o1.ToString());  Decimal d2 = Decimal.Parse(o2.ToString());  return d1*d2; } #endregion}public class OperDiv:IOper{ public OperDiv() {  //  // TODO: 在此处添加构造函数逻辑  // } #region IOper 成员 public object Oper(object o1, object o2) {  Decimal d1 = Decimal.Parse(o1.ToString());  Decimal d2 = Decimal.Parse(o2.ToString());  return d1/d2; } #endregion}}OperFactory.csusing System;namespace Calculate{ /// summary /// OperFactory 的摘要说明。 /// 计算符接口工厂 /// /summary public class OperFactory {  public OperFactory()  {  }  public IOper CreateOper(string Oper)  {   if(Oper.Equals("+"))   {    IOper p = new OperAdd();    return p;   }   if(Oper.Equals("-"))   {    IOper p = new OperDec();    return p;   }   if(Oper.Equals("*"))   {    IOper p = new OperRide();    return p;   }   if(Oper.Equals("/"))   {    IOper p = new OperDiv();    return p;   }   return null;  } }}Calculate.csusing System;using System.Collections;namespace Calculate{ /// summary /// Calculate 的摘要说明。 /// 计算实现主类 /// /summary public class Calculate {  /// summary  /// 算术符栈  /// /summary  private ArrayList HList;  /// summary  /// 数值栈  /// /summary  public ArrayList Vlist;  /// summary  /// 读算试工具  /// /summary  private CalUtility cu;  /// summary  /// 运算操作器工厂  /// /summary  private OperFactory of;  /// summary  /// 构造方法  /// /summary  /// param name="str"算式/param  public Calculate(string str)  {   //   // TODO: 在此处添加构造函数逻辑   //   HList = new ArrayList();   Vlist = new ArrayList();   of = new OperFactory();   cu = new CalUtility(str);  }  /// summary  /// 开始计算  /// /summary  public object DoCal()  {   string strTmp=cu.getItem();   while(true)   {    if(cu.IsNum(strTmp))    {     //如果是数值,则写入数据栈     Vlist.Add(strTmp);    }    else    {     //数值     Cal(strTmp);    }    if(strTmp.Equals(""))     break;    strTmp=cu.getItem();   }   return Vlist[0];  }  /// summary  /// 计算  /// /summary  /// param name="str"计算符/param  private void Cal(string str)  {   //符号表为空,而且当前符号为"",则认为已经计算完毕   if(str.Equals("")&&HList.Count==0)    return;   if(HList.Count0)   {    //符号是否可以对消?    if(HList[HList.Count-1].ToString().Equals("(") && str.Equals(")"))    {     HList.RemoveAt(HList.Count-1);     if(HList.Count0)     {      str=HList[HList.Count-1].ToString();      HList.RemoveAt(HList.Count-1);      Cal(str);     }     return;    }    //比较优先级    if(cu.Compare(HList[HList.Count-1].ToString(),str))    {     //如果优先,则计算     IOper p = of.CreateOper(HList[HList.Count -1].ToString());     if(p!=null)     {      Vlist[Vlist.Count -2] = p.Oper(Vlist[Vlist.Count-2],Vlist[Vlist.Count-1]);      HList.RemoveAt(HList.Count -1);      Vlist.RemoveAt(Vlist.Count -1);      Cal(str);     }     return;    }    if(!str.Equals(""))     HList.Add(str);   }   else   {    if(!str.Equals(""))     HList.Add(str);   }  } }}

  后记

  使用这种方法,我们可以完成更复杂的混合运算,比如说:可以支持函数运算的混合运算,更进一步,可以支持自定义函数的混合运算,最终可以将这种算法运用在自定义报表、工资处理等等应用领域,很希望有相关兴趣的朋友与我交流。

来源:https://www.tulaoshi.com/n/20160219/1610644.html

延伸阅读
所谓托盘程序顾名思义就是象托起的盘子一样的程序。而所谓的托起的盘子就是程序运行中显示出的图标,而托起的位置就是视窗系统的的工具栏了。托盘程序具有直观、占用屏幕空间较小并且可以为它定义多个功能菜单,这就给操作者带来了方便,所以越来越多的程序设计者都把程序设计成托盘这种方式。我们已经看过了用其他语言设计托盘程序的例子...
一、 简介 本文将细致地介绍用C#来实现游戏Reversi的完整过程。游戏界面如下图所示。 二、 背景 我最开始写这个程序是为了作为学习C#和.NET编程的一个练习。Reversi-或Othello一是一个相当有趣且相当流行的游戏,它仅要求几个基本元素和简单的游戏规则。所以,它是学习一个新的编程环境的良好选择。 该程序的第一个...
网络代理程序的种类非常多,根据代理服务程序代理的协议不同,分成HTTP代理服务程序、FTP代理服务程序等,运行代理服务程序的服务器也就称为HTTP代理服务器和FTP代理服务器。在本节中介绍的Web代理服务程序代理的就是HTTP协议。 一.网络代理的类型及实现原理: 网络代理服务根据工作层次,一般可分为应用层代理、传输层代理和SO...
ICMP就是所谓的Internet控制报文协议(Internet Control Message Protocol),在网络中,一般用它来传递差错报文以及其他应注意的信息。ICMP一般被认为是和IP协议同一层的协议,IMCP报文通常被IP层或者更高层的协议(如:TCP或者UDP)使用,ICMP对于互联网以及其他基于IP协议的网络的正常运行起着非常重要的作用。有许多重要的网络程序都是...
       在我们的开发项目中使用MVC(Model-View-Control)模式的益处是,可以完全降低业务层和应用表示层的相互影响。此外, 我们会有完全独立的对象来操作表示层。MVC在我们项目中提供的这种对象和层之间的独立,将使我们的维护变得更简单使 我们的代码重用变得很容易(下面你将看到)。 ...

经验教程

204

收藏

13
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部