C#解析字符串公式
/// <summary>
/// 中缀表达式到逆波兰表达式的转换及求值
/// </summary>
public class RpnExpression
{ #region 定义属性
int Top = -1;
#endregion /// <summary>
/// 检查中缀表达式是否合法
/// </summary>
/// <param name="exp"></param>
/// <returns></returns>
public bool IsRight(string exp)
{
string pMatch = @"\([^\(^\)]+\)";//匹配最“内”层括号及表达式
string numberMatch = @"\d+(\.\d+)?";//匹配数字
string exMatch = @"^0([-+*/]0)*$";//匹配无括号的、用0替换所有的数字后的表达式 exp = Regex.Replace(exp, numberMatch, "0");//为简化检测,用0替换所有的数字
while (Regex.IsMatch(exp, pMatch))
{
foreach (Match match in Regex.Matches(exp, pMatch))
{
string tmp = match.Value;
tmp = tmp.Substring(1, tmp.Length - 2);//去掉 "("和 ")"
if (!Regex.IsMatch(tmp, exMatch)) return false;
}
exp = Regex.Replace(exp, pMatch, "0");//将最内层的括号及括号内表达式直接用一个0代替
} return Regex.IsMatch(exp, exMatch);
} #region 生成逆波兰表达式
/// <summary>
/// 获取逆波兰表达式
/// </summary>
/// <param name="exp"></param>
/// <returns></returns>
public string RpnExp(string exp)
{
string S = ""; //后缀
char[] Operators = new char[exp.Length]; for (int i = 0; i < exp.Length; i++)
{
char C = exp[i];
switch (C)
{
case ' ': //忽略空格
break;
case '+': //操作符
case '-':
while (Top >= 0) //栈不为空时
{
char c = Operators[Top--]; //pop Operator
if (c == '(')
{
Operators[++Top] = c; //push Operator
break;
}
else
{
S = S + c;
}
}
Operators[++Top] = C; //push Operator
S += " ";
break;
case '*': //忽略空格
case '/':
while (Top >= 0) //栈不为空时
{
char c = Operators[Top--]; //pop Operator
if (c == '(')
{
Operators[++Top] = c; //push Operator
break;
}
else
{
if (c == '+' || c == '-')
{
Operators[++Top] = c; //push Operator
break;
}
else
{
S = S + c;
}
}
}
Operators[++Top] = C; //push Operator
S += " ";
break;
case '(':
Operators[++Top] = C;
S += " ";
break;
case ')':
while (Top >= 0) //栈不为空时
{
char c = Operators[Top--]; //pop Operator
if (c == '(')
{
break;
}
else
{
S = S + c;
}
}
S += " ";
break;
default:
S = S + C;
break; }
}
while (Top >= 0)
{
S = S + Operators[Top--]; //pop Operator
}
return S;
} #endregion #region 取逆波兰表达式的值
/// <summary>
/// 获取逆波兰表达式的值
/// </summary>
/// <param name="rpnExp"></param>
/// <returns></returns>
public double GetValueByRpn(string rpnExp)
{
//后缀表达式计算
double[] Operands = new double[rpnExp.Length];
double x, y, v;
Top = -1;
string Operand = "";
for (int i = 0; i < rpnExp.Length; i++)
{
char c = rpnExp[i];
if ((c >= '0' && c <= '9') || c == '.')
{
Operand += c;
} if ((c == ' ' || i == rpnExp.Length - 1) && Operand != "") //Update
{
Operands[++Top] = System.Convert.ToDouble(Operand); //push Operands
Operand = "";
} if (c == '+' || c == '-' || c == '*' || c == '/')
{
if ((Operand != ""))
{
Operands[++Top] = System.Convert.ToDouble(Operand); //push Operands
Operand = "";
}
y = Operands[Top--]; //pop 双目运算符的第二操作数 (后进先出)注意操作数顺序对除法的影响
x = Operands[Top--]; //pop 双目运算符的第一操作数
switch (c)
{
case '+':
v = x + y;
break;
case '-':
v = x - y;
break;
case '*':
v = x * y;
break;
case '/':
v = x / y; // 第一操作数 / 第二操作数 注意操作数顺序对除法的影响
break;
default:
v = 0;
break;
}
Operands[++Top] = v; //push 中间结果再次入栈
}
}
v = Operands[Top--]; //pop 最终结果
return v;
}
#endregion
}
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#解析字符串公式的更多相关文章
- NVelocity解析字符串
之前都是先从模板文件里面读取html字符串,现在要求将模板存入数据库或缓存了,怎么办呢?在网上找了下资料,终于找到解决办法. 如下: public class NVelocityHelper { // ...
- sql 解析字符串添加到临时表中 sql存储过程in 参数输入
sql 解析字符串添加到临时表中 sql存储过程in 参数输入 解决方法 把字符串解析 添加到 临时表中 SELECT * into #临时表 FROM dbo.Func_SplitOneCol ...
- [转]用Objective-C实现简单的数学字符串公式的计算
好友第一次用写技术分享,这么多年都没见他正经的写点东西.那天突然抬头问我,Objective-C有没字符串计算的.我说,没有.后来他默默实现了,特为他转发,表示支持. ================ ...
- 转: c# 字符串公式计算
C# 自动计算字符串公式的值(三种方式) 从网络上找到这段源码,重新整理后测试通过. 有三种方式可自动计算字符串公式的值:1. 最简单的方式,由SQL语句计算2. 使用Microsoft.Javasc ...
- java代码中fastjson生成字符串和解析字符串的方法和javascript文件中字符串和json数组之间的转换方法
1.java代码中fastjson生成字符串和解析字符串的方法 List<TemplateFull> templateFulls = new ArrayList<TemplateFu ...
- JSON解析字符串
JSON解析字符串 JSON 解析字符串时,应按严格的标准,否则无法解析: str1 = '{"str":"string","number" ...
- java解析字符串拆分单独元素
有时候,需求要求传递多个字符串参数,但是方法参数已经固定为单个String,笔者在学习unity和android之间的消息传递时就遇到这个问题,所以就写了这么一个解析字符串拆分单独元素的方法. 示例: ...
- 6.游戏特别离不开脚本(3)-JS脚本操作java(2)(直接解析JS公式,并非完整JS文件或者函数)
在游戏中可以考虑数据由javabean保存,逻辑方法由JS提供. public class Bean4JS { private int id; private String name; private ...
- python,json解析字符串时ValueError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
今天写测试工具的时候,去excel取数据,用json解析字符串为字典时报错,后经调试,发现是单引号的原因,将单引号换位双引号即可 def getExcelValue_to_dic(filepath): ...
随机推荐
- 封装一个C#日志类Loger
public class Loger { /// <summary> /// 写入日志 /// </summary> /// <param name="cont ...
- python pip安装扩展报错
1.安装tldr报错 (1)报错详情: [root@linuxnode1 ~]# pip install tldrCollecting tldr Downloading https://files.p ...
- 手把手教你接口自动化测试 – SoapUI & Groovy【转】
手把手教你接口自动化测试 – SoapUI & Groovy Posted on 2015-01-21 09:38 WadeXu 阅读(12741) 评论(10) 编辑 收藏 手把手教你接口自 ...
- 2016.9.15初中部上午NOIP普及组比赛总结
2016.9.15初中部上午NOIP普及组比赛总结 2016.09.15[初中部 NOIP普及组 ]模拟赛 又翻车了!表示时超和空超很可恨! 进度 比赛:AC+0+0+20=120 改题:AC+80+ ...
- Spring Cloud Alibaba发布第二个版本,Spring 发来贺电
还是熟悉的面孔,还是熟悉的味道,不同的是,这次的配方升级了. 今年10月底,Spring Cloud联合创始人Spencer Gibb在Spring官网的博客页面宣布:阿里巴巴开源 Spring Cl ...
- day05 创建用户过程、文件夹,文件等权限修改等
linux创建用户时修改到的文件 /etc/passwd //存放用户信息 /etc/shadow //存放用户密码信息 /etc/group //存放用户组信息 /etc/gshadow //存放组 ...
- 杂项-公司:SAMSUNG
ylbtech-杂项-公司:SAMSUNG 三星集团是韩国最大的跨国企业集团,同时也是上市企业全球500强,三星集团包括众多的国际下属企业,旗下子公司有:三星电子.三星物产.三星航空.三星人寿保险等, ...
- Spring MVC(四)--控制器接受pojo参数
以pojo的方式传递参数适用于参数较多的情况,或者是传递对象的这种情况,比如要创建一个用户,用户有十多个属性,此时就可以通过用户的pojo对象来传参数,需要注意的是前端各字段的名称和pojo对应的属性 ...
- 图片转成base64 跨域等安全限制及解决方案
把其他域的图片在canvas中转换为base64时,会遇到跨域安全限制. 目前,唯一可行的方案是,把图片文件以arraybuffer的形式ajax下载下来,然后直接转base4. 但是,这样有个毛病, ...
- [Ynoi2012]D1T1
题目 套路的根号分治啊 我们设置一个值\(S\) 对于\(S\leq x\)的操作,我们直接暴力修改,显然这样只会修改\(\frac{n}{S}\)次,所以我们需要一个能够\(O(1)\)修改的数据结 ...