1. /// <summary>
  2. /// 中缀表达式到逆波兰表达式的转换及求值
  3. /// </summary>
  4. public class RpnExpression
  5. {
  6.  
  7. #region 定义属性
  8. int Top = -1;
  9. #endregion
  10.  
  11. /// <summary>
  12. /// 检查中缀表达式是否合法
  13. /// </summary>
  14. /// <param name="exp"></param>
  15. /// <returns></returns>
  16. public bool IsRight(string exp)
  17. {
  18. string pMatch = @"\([^\(^\)]+\)";//匹配最“内”层括号及表达式
  19. string numberMatch = @"\d+(\.\d+)?";//匹配数字
  20. string exMatch = @"^0([-+*/]0)*$";//匹配无括号的、用0替换所有的数字后的表达式
  21.  
  22. exp = Regex.Replace(exp, numberMatch, "0");//为简化检测,用0替换所有的数字
  23. while (Regex.IsMatch(exp, pMatch))
  24. {
  25. foreach (Match match in Regex.Matches(exp, pMatch))
  26. {
  27. string tmp = match.Value;
  28. tmp = tmp.Substring(1, tmp.Length - 2);//去掉 "("和 ")"
  29. if (!Regex.IsMatch(tmp, exMatch)) return false;
  30. }
  31. exp = Regex.Replace(exp, pMatch, "0");//将最内层的括号及括号内表达式直接用一个0代替
  32. }
  33.  
  34. return Regex.IsMatch(exp, exMatch);
  35. }
  36.  
  37. #region 生成逆波兰表达式
  38. /// <summary>
  39. /// 获取逆波兰表达式
  40. /// </summary>
  41. /// <param name="exp"></param>
  42. /// <returns></returns>
  43. public string RpnExp(string exp)
  44. {
  45. string S = ""; //后缀
  46. char[] Operators = new char[exp.Length];
  47.  
  48. for (int i = 0; i < exp.Length; i++)
  49. {
  50. char C = exp[i];
  51. switch (C)
  52. {
  53. case ' ': //忽略空格
  54. break;
  55. case '+': //操作符
  56. case '-':
  57. while (Top >= 0) //栈不为空时
  58. {
  59. char c = Operators[Top--]; //pop Operator
  60. if (c == '(')
  61. {
  62. Operators[++Top] = c; //push Operator
  63. break;
  64. }
  65. else
  66. {
  67. S = S + c;
  68. }
  69. }
  70. Operators[++Top] = C; //push Operator
  71. S += " ";
  72. break;
  73. case '*': //忽略空格
  74. case '/':
  75. while (Top >= 0) //栈不为空时
  76. {
  77. char c = Operators[Top--]; //pop Operator
  78. if (c == '(')
  79. {
  80. Operators[++Top] = c; //push Operator
  81. break;
  82. }
  83. else
  84. {
  85. if (c == '+' || c == '-')
  86. {
  87. Operators[++Top] = c; //push Operator
  88. break;
  89. }
  90. else
  91. {
  92. S = S + c;
  93. }
  94. }
  95. }
  96. Operators[++Top] = C; //push Operator
  97. S += " ";
  98. break;
  99. case '(':
  100. Operators[++Top] = C;
  101. S += " ";
  102. break;
  103. case ')':
  104. while (Top >= 0) //栈不为空时
  105. {
  106. char c = Operators[Top--]; //pop Operator
  107. if (c == '(')
  108. {
  109. break;
  110. }
  111. else
  112. {
  113. S = S + c;
  114. }
  115. }
  116. S += " ";
  117. break;
  118. default:
  119. S = S + C;
  120. break;
  121.  
  122. }
  123. }
  124. while (Top >= 0)
  125. {
  126. S = S + Operators[Top--]; //pop Operator
  127. }
  128. return S;
  129. }
  130.  
  131. #endregion
  132.  
  133. #region 取逆波兰表达式的值
  134. /// <summary>
  135. /// 获取逆波兰表达式的值
  136. /// </summary>
  137. /// <param name="rpnExp"></param>
  138. /// <returns></returns>
  139. public double GetValueByRpn(string rpnExp)
  140. {
  141. //后缀表达式计算
  142. double[] Operands = new double[rpnExp.Length];
  143. double x, y, v;
  144. Top = -1;
  145. string Operand = "";
  146. for (int i = 0; i < rpnExp.Length; i++)
  147. {
  148. char c = rpnExp[i];
  149. if ((c >= '0' && c <= '9') || c == '.')
  150. {
  151. Operand += c;
  152. }
  153.  
  154. if ((c == ' ' || i == rpnExp.Length - 1) && Operand != "") //Update
  155. {
  156. Operands[++Top] = System.Convert.ToDouble(Operand); //push Operands
  157. Operand = "";
  158. }
  159.  
  160. if (c == '+' || c == '-' || c == '*' || c == '/')
  161. {
  162. if ((Operand != ""))
  163. {
  164. Operands[++Top] = System.Convert.ToDouble(Operand); //push Operands
  165. Operand = "";
  166. }
  167. y = Operands[Top--]; //pop 双目运算符的第二操作数 (后进先出)注意操作数顺序对除法的影响
  168. x = Operands[Top--]; //pop 双目运算符的第一操作数
  169. switch (c)
  170. {
  171. case '+':
  172. v = x + y;
  173. break;
  174. case '-':
  175. v = x - y;
  176. break;
  177. case '*':
  178. v = x * y;
  179. break;
  180. case '/':
  181. v = x / y; // 第一操作数 / 第二操作数 注意操作数顺序对除法的影响
  182. break;
  183. default:
  184. v = 0;
  185. break;
  186. }
  187. Operands[++Top] = v; //push 中间结果再次入栈
  188. }
  189. }
  190. v = Operands[Top--]; //pop 最终结果
  191. return v;
  192. }
  193. #endregion
  194. }

1.先说明下这个实现算法--逆波兰表达式

表达式一般由操作数(Operand)、运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间,

这称为中缀表达式(Infix Expression),如A+B。

波兰数学家Jan Lukasiewicz提出了另一种数学表示法,它有两种表示形式:

把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;

把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+;

其中,逆波兰表达式在编译技术中有着普遍的应用。

算法:

一、 将中缀表达式转换成后缀表达式算法:

1、从左至右扫描一中缀表达式。

2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈

3、若读取的是运算符

(1) 该运算符为左括号"(",则直接存入运算符堆栈。

(2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。

(3) 该运算符为非括号运算符:

(a) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。

(b) 若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。

(c) 若比运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。

4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空

示例:

(1.2+3.5)*2/4 =>1.2 3.5+ 2* 4/

下面给出实现代码:

C#解析字符串公式的更多相关文章

  1. NVelocity解析字符串

    之前都是先从模板文件里面读取html字符串,现在要求将模板存入数据库或缓存了,怎么办呢?在网上找了下资料,终于找到解决办法. 如下: public class NVelocityHelper { // ...

  2. sql 解析字符串添加到临时表中 sql存储过程in 参数输入

    sql 解析字符串添加到临时表中  sql存储过程in 参数输入 解决方法 把字符串解析 添加到 临时表中 SELECT * into #临时表   FROM dbo.Func_SplitOneCol ...

  3. [转]用Objective-C实现简单的数学字符串公式的计算

    好友第一次用写技术分享,这么多年都没见他正经的写点东西.那天突然抬头问我,Objective-C有没字符串计算的.我说,没有.后来他默默实现了,特为他转发,表示支持. ================ ...

  4. 转: c# 字符串公式计算

    C# 自动计算字符串公式的值(三种方式) 从网络上找到这段源码,重新整理后测试通过. 有三种方式可自动计算字符串公式的值:1. 最简单的方式,由SQL语句计算2. 使用Microsoft.Javasc ...

  5. java代码中fastjson生成字符串和解析字符串的方法和javascript文件中字符串和json数组之间的转换方法

    1.java代码中fastjson生成字符串和解析字符串的方法 List<TemplateFull> templateFulls = new ArrayList<TemplateFu ...

  6. JSON解析字符串

    JSON解析字符串 JSON 解析字符串时,应按严格的标准,否则无法解析: str1 = '{"str":"string","number" ...

  7. java解析字符串拆分单独元素

    有时候,需求要求传递多个字符串参数,但是方法参数已经固定为单个String,笔者在学习unity和android之间的消息传递时就遇到这个问题,所以就写了这么一个解析字符串拆分单独元素的方法. 示例: ...

  8. 6.游戏特别离不开脚本(3)-JS脚本操作java(2)(直接解析JS公式,并非完整JS文件或者函数)

    在游戏中可以考虑数据由javabean保存,逻辑方法由JS提供. public class Bean4JS { private int id; private String name; private ...

  9. python,json解析字符串时ValueError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

    今天写测试工具的时候,去excel取数据,用json解析字符串为字典时报错,后经调试,发现是单引号的原因,将单引号换位双引号即可 def getExcelValue_to_dic(filepath): ...

随机推荐

  1. 使用HttpStaus自定义返回状态

    一.导入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  2. 解决Pycharm无法导入包问题 Unresolved reference

    在pycharm中设置source路径 file–>setting–>project:server–>project structure 将放package的文件夹设置为source ...

  3. JavaSE_11_File类、递归

    1.1 概述File类 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 1.2 构造方法 public File(String pathname ...

  4. 33 N皇后问题

    原题网址:https://www.lintcode.com/zh-cn/old/problem/n-queens/# n皇后问题是将n个皇后放置在n*n的棋盘上,皇后彼此之间不能相互攻击. 给定一个整 ...

  5. C++ const修饰不同类型的用法

    const取自constant的缩写,本意是不变的,不易改变的意思 一.修饰普通变量 const int a = 7; int b = a;         //正确 a = 8;           ...

  6. 使用 Vue.js 和 Chart.js 制作绚丽多彩的图表

    本文作者:Jakub Juszczak 编译:胡子大哈 翻译原文:http://huziketang.com/blog/posts/detail?postId=58e5e0e1a58c240ae35b ...

  7. myeclipse 无法部署项目到jboss服务器 部署不上去

    关于myeclipse部署项目到jboss点击add deployments没有反应的问题,如图 此处点击右键,选择add deployments没有反应,原因是默认的web-root folder为 ...

  8. python3-常用模块之re

    正则表达式 定义: 正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑. 是一种独立的规 ...

  9. C++【string】用法和例子

    /*** * string 基础api复习 * 8 AUG 2018 */ #include <iostream> #include <string> using namesp ...

  10. List循环添加对象时遇到问题的解决

    var temp=new handleData(); foreach(var t in data) { temp.DataValue = t.DataValue; temp.CreateTime = ...