转化字符串表达式为数学公式并算出结果
2011-10-10 09:43
537 查看
/*
* FormulaCalculator.java
*
* Created on 2007年9月18日, 上午11:40
* @title 转化字符串表达式为数学公式并算出结果
* @description 转化字符串表达式为数学公式并算出结果
* 注意:为了区分负号,这边使用#代替减号
* 使用方法:
* FormulaCalculator calculator=new FormulaCalculator();
* calculator.getResult("10.23#20.67*(5.12+7.82)/2",2);
* v1.0.0 created by chenfc
*
*/
package org.jceun;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FormulaCalculator ...{
private boolean isRightFormat =
true;
public String DIVISOR_EQUALS_ZERO="0.0"
;//除数为零时的返回值
/** *//**
* 为了区分负号,这边使用#代替减号
* @param formula 字符串表达式
* @return 返回公式计算结果
*/
public
double getResult(String formula)...{
double returnValue = 0;
try
... {
returnValue = doAnalysis(formula);
}catch
(NumberFormatException nfe)...{
System.out.println("公式格式有误,请检查:" + formula);
}catch
(Exception e)...{
e.printStackTrace();
}
if
( ! isRightFormat)...{
System.out.println("公式格式有误,请检查:" + formula);
}
return returnValue;
}
/** *//**
* 采用BigDecimal.ROUND_HALF_UP方式返回指定精度的运算结果
* @param formula 公式
* @param decimalPlace 要保留的小数位数
* @return 返回公式计算结果
*/
public
String getResult(String formula,int
decimalPlace)...{
return getResult(formula,decimalPlace,BigDecimal.ROUND_HALF_UP);
}
/** *//**
* 返回指定精度及舍去尾数的策略的运算结果
* @param formula 公式
* @param decimalPlace 要保留的小数位数
* @param roundMethod 舍去尾数的策略
* 可取值有BigDecimal.ROUND_HALF_UP BigDecimal.ROUND_HALF_DOWN祥见BigDecimal
* @return 返回公式计算结果
*/
public
String getResult(String formula,int
decimalPlace,int
roundMethod)...{
double result=getResult(formula);
if(result==Double.MAX_VALUE)
return DIVISOR_EQUALS_ZERO;
else
return numberAround(result,decimalPlace,roundMethod);
}
private
double doAnalysis(String formula)...{
double returnValue = 0;
LinkedList<Integer> stack
= new LinkedList<Integer>
();
int curPos = 0
;
String beforePart = "";
String afterPart = "";
String calculator = "";
isRightFormat = true;
while
(isRightFormat&&
(formula.indexOf('
( ' ) >= 0||
formula.indexOf(')
') >= 0
))...{
curPos = 0;
for
( char s : formula.toCharArray())...{
if
(s == '(')
... {
stack.add(curPos);
}else
if (s == ')')...
{
if
(stack.size() >
0 )...{
beforePart = formula.substring(0, stack.getLast());
afterPart = formula.substring(curPos + 1);
calculator = formula.substring(stack.getLast() + 1, curPos);
formula = beforePart + doCalculation(calculator) + afterPart;
stack.clear();
break;
}else
... {
System.out.println("有未关闭的右括号!");
isRightFormat = false;
}
}
curPos++;
}
if
(stack.size() >
0 )...{
System.out.println("有未关闭的左括号!");
break;
}
}
if
(isRightFormat)...{
returnValue = doCalculation(formula);
}
return returnValue;
}
/** *//**
* 为了区分负号,这边使用#代替减号
*/
private
double doCalculation(String formula) ...{
ArrayList<Double> values
=
new ArrayList<Double>();
ArrayList<String> operators =
new ArrayList<String>();
int curPos = 0
;
int prePos = 0
;
for
( char s : formula.toCharArray()) ...{
if
(s == '+'
|| s == '
#' ||
s == '*'
|| s ==
'/')
... {
values.add(Double.parseDouble(formula.substring(prePos, curPos)
.trim()));
operators.add("" + s);
prePos = curPos +
1;
}
curPos++;
}
values.add(Double.parseDouble(formula.substring(prePos).trim()));
char op;
for
(curPos =
operators.size() -
1 ; curPos >= 0; curPos--) ...{
op = operators.get(curPos).charAt(0);
switch
(op) ...{
case '*
':
values.add(curPos, values.get(curPos) * values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
case '/
':
if(values.get(curPos + 1).doubleValue()==0.0
)//除数为零时
values.add(curPos, new Double(getDefaultValue()));
else
values.add(curPos, values.get(curPos) / values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
}
}
for
(curPos =
operators.size() -
1 ; curPos >= 0; curPos--) ...{
op = operators.get(curPos).charAt(0);
switch
(op) ...{
case '+
':
values.add(curPos, values.get(curPos) + values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
case '#
':
values.add(curPos, values.get(curPos) - values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
}
}
return values.get(0).doubleValue();
}
/** *//**
* 对数字进行四舍五入
* @param dN 要四舍五入的数
* @param decimalPlace 精度
* @param roundMethod 舍去尾数的策略
* 可取值有BigDecimal.ROUND_HALF_UP BigDecimal.ROUND_HALF_DOWN祥见BigDecimal
*/
public
String numberAround(double
dN,int decimalPlace, int roundMethod)...{
BigDecimal bd = new BigDecimal(String.valueOf(dN));
bd = bd.setScale(decimalPlace, roundMethod);
return String.valueOf(bd);
}
/** *//**
* 对给定的字符串进行模式匹配
* @param str 要匹配的字符串
* @param regix 模式
* @return 返回匹配结果,成功为true,否则为false
**/
public
boolean
check(String str,String regix)...{
boolean result=false;
Pattern p=Pattern.compile(regix);
Matcher m =p.matcher(str);
result=m.matches();
return result;
}
}
//:表达式解析-两栈算法.txt
//:Arithmetic.java
package citi;
import java.util.Iterator;
import java.util.Stack;
import java.util.ArrayList;
public class Arithmetic{
//定义操作符,为简单起见,只涉及四则运算,可相应扩充之
static String Operators= "+-*/()# ";
//定义操作符的比较优先级,
//其中1表示前面的操作符优于后面的操作符
// -1表示前面的操作符低于后面的操作符
// 0表示前面的操作符等于后面的操作符
// 2表示前面的操作符不可能与后面的操作符相比较,如果碰到,则表达式有错
//PrecedeList[0][]表示+和+-*/()#这七个操作符相比较的优先级
//PrecedeList[1][]表示-和+-*/()#这七个操作符相比较的优先级
//以此类推
static byte PrecedeList[][]={
{ 1, 1,-1,-1,-1, 1, 1},
{ 1, 1,-1,-1,-1, 1, 1},
{ 1, 1, 1, 1,-1, 1, 1},
{ 1, 1, 1, 1,-1, 1, 1},
{-1,-1,-1,-1,-1, 0, 2},
{ 1, 1, 1, 1, 2, 1, 1},
{-1,-1,-1,-1,-1, 2, 0}};
//定义数据中可能出现的数字和小数点,可以扩展
static String Numbers= "0123456789. ";
private Stack Operator,Operand;
private ArrayList Expression;
public Arithmetic(String inputStr){
Operator=new Stack();
Operator.push( "# ");
Operand=new Stack();
Expression=new ArrayList();
Parse(inputStr);
}
//解析输入的表达式,将操作符和数据分开
//如输入表达式2+3*(32-2)则解析成2 + 3 * ( 32 - 2 )这九个字符串
private void Parse(String instr){
String single;
int temp;
String tempstr= "# ";
for(int i=0;i <instr.length();i++){
single=instr.substring(i,i+1);
//排除非操作符、数字的非法输入,如2+3m
//Operators.indexOf(single)==6排除#
if(Numbers.indexOf(single) <0 && (Operators.indexOf(single) <0 || Operators.indexOf(single)==6)){
System.out.println( "Input have wrong char: "+single);
Expression.clear();
return;
}
//获得前一个输入字符
temp=Expression.size()-1;
if(temp> -1){
tempstr=(String)Expression.get(temp);
}
//排除连续两个操作符的情况,如3**2
if(Operators.indexOf(single)> -1 && temp> -1 && Operators.indexOf(tempstr)> -1){
System.out.println( "Input have wrong format,two Operators are conjoint ");
Expression.clear();
return;
}
//如果当前字符是数字(包括.)而且前一字符也是数字,则将当前字符加到前一字符后面
//其他情况均新添加一个元素
if(Operators.indexOf(single) <0 && temp> -1 && Operators.indexOf(tempstr) <0){
Expression.set(temp,tempstr+single);
}
else{
Expression.add(single);//其他情况均新添加一个元素
}
}
//为了算法处理方便起见,添加特殊字符#
Expression.add( "# ");
}
//比较两个操作符的优先级
private byte Precede(String firstOperator,String secondOperator){
return PrecedeList[Operators.indexOf(firstOperator)][Operators.indexOf(secondOperator)];
}
//对两个数据字符串进行运算
private double Operate(String firstOperand,String Operator,String secondOperand){
if(Operator.equals( "+ ")){
return (Double.parseDouble(firstOperand)+Double.parseDouble(secondOperand));
}
else if(Operator.equals( "- ")){
return (Double.parseDouble(firstOperand)-Double.parseDouble(secondOperand));
}
else if(Operator.equals( "* ")){
return (Double.parseDouble(firstOperand)*Double.parseDouble(secondOperand));
}
else if(Operator.equals( "/ ")){
return (Double.parseDouble(firstOperand)/Double.parseDouble(secondOperand));
}
else{
System.out.println( "Operator is wrong!Can throw a Exception ");
return 0;
}
}
//采用两个栈对接解析后的表达式进行运算
public double Compute(){
if(Expression.isEmpty()){
System.out.println( "Expresion is empty ");
return 0;
}
Iterator it = Expression.iterator();
String single;
String firstOperand,secondOperand;
single=(String)it.next();
while(!(single.equals( "# ") && Operator.peek().equals( "# "))){
if(Operators.indexOf(single) <0){
Operand.push(single);single=(String)it.next();
}
else{
switch(Precede((String)Operator.peek(),single)){
case -1:Operator.push(single);single=(String)it.next();break;
case 0: Operator.pop();single=(String)it.next();break;
case 1:
secondOperand=(String)Operand.pop();
firstOperand=(String)Operand.pop();
Operand.push(String.valueOf(Operate(firstOperand,(String)Operator.pop(),secondOperand)));break;
case 2: System.out.println( "Expression is wrong!Can throw a Exception ");break;
}
}
}
return Double.parseDouble((String)Operand.pop());
}
public static void main(String[] args){
long t1 = System.currentTimeMillis();
Arithmetic t=new Arithmetic(args[0]);
System.out.println(t.Compute());
long t2 = System.currentTimeMillis();
System.out.println( "Time needed: " + (t2 - t1));
}
}
C# code
using System;
using System.Text;
namespace Lentro.Edu.Ch02
{
public class Expression
{
private StackSimple<int> theStack;
public StringBuilder suffix = new StringBuilder();
/**
* 检查该字符是否为括号
*/
private bool isParen(char c)
{
if (c == '{' || c == '[' || c == '(' || c == ')' || c == ']' || c == '}')
return true;
else
return false;
}
/**
* 检查是否为左括号
*/
private bool isLeftParen(char c)
{
if (c == '{' || c == '[' || c == '(')
return true;
else
return false;
}
/**
* 判断指定的操作符是否为 '+' 或者 '-'
*/
private bool isAddOrSub(int oper)
{
return oper == '+' || oper == '-';
}
/**
* 检查是否为数字
*/
private bool isNumber(int ch)
{
return ch >= 48 && ch <= 57;
}
/**
* 检查表达式是否合法
*/
private bool checkExp(String exp)
{
char[] ch = exp.ToCharArray();
StackSimple<int> theStackXInt = new StackSimple<int>(exp.Length / 2);
/**
* 遍历表达式,只处理括号部分
*/
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
if (isParen(c))
{
/**
* 左括号进栈
*/
if (isLeftParen(c))
{
theStackXInt.Push(c);
}
else
{
if (theStackXInt.IsEmpty())
{
return false;
}
int left = theStackXInt.Pop();
switch (c)
{
case '}':
if (left != '{')
return false;
break;
case ']':
if (left != '[')
return false;
break;
case ')':
if (left != '(')
return false;
break;
}
}
}
}
if (theStackXInt.IsEmpty())
{
return true;
}
else
{
return false;
}
}
/**
* 根据当前操作符处理之前在栈中的操作符,当前操作符暂不处理,放入栈中
*/
private void processOper(char oper)
{
while (!theStack.IsEmpty())
{
int currTop = theStack.Pop();
/**
* 如果是左括号,则不予处理,将括号返回进栈
*
* 若得到的操作符,则进一步判断
*/
if (currTop == '(')
{
theStack.Push(currTop);
break;
}
else
{
if (this.isAddOrSub(currTop))
{
if (this.isAddOrSub(oper))
{
this.suffix.Append((char)currTop);
}
else
{
this.theStack.Push(currTop);
break;
}
}
else
{
this.suffix.Append((char)currTop);
break;
}
}
}
/**
* 当前操作符进栈
*/
theStack.Push(oper);
}
/**
* 处理括弧.
*
* 如果为左括弧,直接进栈;
*
* 否则为右括弧,现将这一对括号中的操作符优先处理完
*/
private void processParen(char paren)
{
if (this.isLeftParen(paren))
{
this.theStack.Push(paren);
}
else
{
while (!theStack.IsEmpty())
{
int chx = theStack.Pop();
if (chx == '(')
break;
else
suffix.Append((char)chx);
}
}
}
/**
* 将正确的中缀表达式转为后缀表达式
*/
private void doTrans(String exp)
{
theStack = new StackSimple<int>(exp.Length);
if (this.checkExp(exp))
{
char[] ch = exp.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
switch (c)
{
case '+':
case '-':
case '*':
case '/':
this.processOper(c);
break;
case '(':
case ')':
this.processParen(c);
break;
default:
this.suffix.Append(c);
break;
}
}
while (!this.theStack.IsEmpty())
{
this.suffix.Append((char)this.theStack.Pop());
}
}
}
/**
* 计算表达式
*/
public int clac(String exp)
{
this.doTrans(exp);
String suff = this.suffix.ToString();
StackSimple<int> stack = new StackSimple<int>(suff.Length);
if (suff == null || suff.Length == 0)
{
}
else
{
char[] ch = suff.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
if (this.isNumber(c))
{
stack.Push(c - 48);
}
else
{
int operand2 = stack.Pop();
int operand1 = stack.Pop();
switch (c)
{
case '+':
stack.Push(operand1 + operand2);
break;
case '-':
stack.Push(operand1 - operand2);
break;
case '*':
stack.Push(operand1 * operand2);
break;
case '/':
stack.Push(operand1 / operand2);
break;
}
}
}
}
return stack.Peep();
}
}
}
其中StackSimple是自己写的一个简单的栈实现
C# code
using System;
namespace Lentro.Edu.Ch02
{
/// <summary>
/// 用于演示栈(LIFO)的内部实现机制
///
/// xfeng/2010-05-07
/// </summary>
public class StackSimple<T>
{
//栈默认的初始容量大小
private const int DEFAULT_SIZE = 10;
private T[] array;
private int index;
/// <summary>
/// 初始化 Stack 类的新实例,该实例为空并且具有默认初始容量。
/// </summary>
public StackSimple()
: this(DEFAULT_SIZE) { }
/// <summary>
/// 初始化 Stack 类的新实例,该实例为空并且具有指定的初始容量。
/// </summary>
/// <param name="size"></param>
public StackSimple(int size)
{
index = -1;
this.array = new T[size];
}
private int _count;
/// <summary>
/// 获取 Stack 中包含的元素数。
/// </summary>
public int Count
{
get { return _count; }
}
/// <summary>
/// 清空栈
/// </summary>
public void Clear()
{
for (int i = 0; i < array.Length; i++)
{
array[i] = default(T);
this.index = -1;
this._count = 0;
}
}
public Boolean IsEmpty()
{
return this._count == 0;
}
/// <summary>
/// 返回位于 Stack 顶部的对象但不将其移除。
/// </summary>
/// <returns>位于 Stack 顶部的 Object。</returns>
public T Peep()
{
return this.index < 0 ? default(T) : this.array[this.index];
}
/// <summary>
/// 移除并返回位于 Stack 顶部的对象。
/// </summary>
/// <returns>从 Stack 的顶部移除的 Object。 </returns>
public T Pop()
{
T obj = this.index < 0 ? default(T) : this.array[this.index];
if (null != obj)
{
this.index--;
this._count--;
//this.array[this.index] = default(T);
}
return obj;
}
/// <summary>
/// 将对象插入 Stack 的顶部。
/// </summary>
public void Push(T obj)
{
if (null != obj)
{
if (this.index >= this.array.Length - 1)
{
T[] temp = new T[this.array.Length * 2];
int count = 0;
foreach (T item in array)
{
temp[count++] = item;
}
this.array = temp;
}
array[++index] = obj;
this._count++;
}
}
}
}
这是那个栈Demo
C#的动态编译,并返回结果
C# code
private void btn_Compute_Click(object sender, EventArgs e)
{
// 声明要计算C#代码,要求必须完整的C#代码
string strCode = @"
using System;
namespace ParseEx
{
public class ParseExC
{
public static double GetValue() //GetValue(int x) //可以带参数
{
return 1+5*8-(Math.Sin(12)*2.5);
}
}
}";
Stopwatch sw = new Stopwatch();
sw.Start();
string strCode = @"
using System;
namespace ParseEx
{
public class ParseExC
{
public static double GetValue()
{"
+ "return " + this.textBox_Text.Text.Trim() + ";" +
@"}
}
}";
CodeDomProvider comp = new CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
StringBuilder codeBuilder = new StringBuilder();
codeBuilder.AppendLine(strCode);
cp.ReferencedAssemblies.Add("System.dll");
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
CompilerResults cr = comp.CompileAssemblyFromSource(cp, codeBuilder.ToString());
if (cr.Errors.HasErrors)
{
MessageBox.Show("Error!");
}
else
{
Assembly a = cr.CompiledAssembly;
if (a != null)
{
Type t = a.GetType("ParseEx.ParseExC");
if (t != null)
{
// 因为是静态调用,不需要创建实例了
// object mode = a.CreateInstance("Mode");
MethodInfo mi = t.GetMethod("GetValue", BindingFlags.Static | BindingFlags.Public);
if (mi != null)
{
double d = (double)mi.Invoke(null, null);
//double d = (double)mi.Invoke(null, new object[] { 1 }) }); //可以带参数
sw.Stop();
this.label_Result.Text = "Result = " + d.ToString() + "; Time = " + sw.Elapsed.ToString();
//MessageBox.Show("Result = " + d.ToString());
}
}
}
}
}
}
* FormulaCalculator.java
*
* Created on 2007年9月18日, 上午11:40
* @title 转化字符串表达式为数学公式并算出结果
* @description 转化字符串表达式为数学公式并算出结果
* 注意:为了区分负号,这边使用#代替减号
* 使用方法:
* FormulaCalculator calculator=new FormulaCalculator();
* calculator.getResult("10.23#20.67*(5.12+7.82)/2",2);
* v1.0.0 created by chenfc
*
*/
package org.jceun;
import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FormulaCalculator ...{
private boolean isRightFormat =
true;
public String DIVISOR_EQUALS_ZERO="0.0"
;//除数为零时的返回值
/** *//**
* 为了区分负号,这边使用#代替减号
* @param formula 字符串表达式
* @return 返回公式计算结果
*/
public
double getResult(String formula)...{
double returnValue = 0;
try
... {
returnValue = doAnalysis(formula);
}catch
(NumberFormatException nfe)...{
System.out.println("公式格式有误,请检查:" + formula);
}catch
(Exception e)...{
e.printStackTrace();
}
if
( ! isRightFormat)...{
System.out.println("公式格式有误,请检查:" + formula);
}
return returnValue;
}
/** *//**
* 采用BigDecimal.ROUND_HALF_UP方式返回指定精度的运算结果
* @param formula 公式
* @param decimalPlace 要保留的小数位数
* @return 返回公式计算结果
*/
public
String getResult(String formula,int
decimalPlace)...{
return getResult(formula,decimalPlace,BigDecimal.ROUND_HALF_UP);
}
/** *//**
* 返回指定精度及舍去尾数的策略的运算结果
* @param formula 公式
* @param decimalPlace 要保留的小数位数
* @param roundMethod 舍去尾数的策略
* 可取值有BigDecimal.ROUND_HALF_UP BigDecimal.ROUND_HALF_DOWN祥见BigDecimal
* @return 返回公式计算结果
*/
public
String getResult(String formula,int
decimalPlace,int
roundMethod)...{
double result=getResult(formula);
if(result==Double.MAX_VALUE)
return DIVISOR_EQUALS_ZERO;
else
return numberAround(result,decimalPlace,roundMethod);
}
private
double doAnalysis(String formula)...{
double returnValue = 0;
LinkedList<Integer> stack
= new LinkedList<Integer>
();
int curPos = 0
;
String beforePart = "";
String afterPart = "";
String calculator = "";
isRightFormat = true;
while
(isRightFormat&&
(formula.indexOf('
( ' ) >= 0||
formula.indexOf(')
') >= 0
))...{
curPos = 0;
for
( char s : formula.toCharArray())...{
if
(s == '(')
... {
stack.add(curPos);
}else
if (s == ')')...
{
if
(stack.size() >
0 )...{
beforePart = formula.substring(0, stack.getLast());
afterPart = formula.substring(curPos + 1);
calculator = formula.substring(stack.getLast() + 1, curPos);
formula = beforePart + doCalculation(calculator) + afterPart;
stack.clear();
break;
}else
... {
System.out.println("有未关闭的右括号!");
isRightFormat = false;
}
}
curPos++;
}
if
(stack.size() >
0 )...{
System.out.println("有未关闭的左括号!");
break;
}
}
if
(isRightFormat)...{
returnValue = doCalculation(formula);
}
return returnValue;
}
/** *//**
* 为了区分负号,这边使用#代替减号
*/
private
double doCalculation(String formula) ...{
ArrayList<Double> values
=
new ArrayList<Double>();
ArrayList<String> operators =
new ArrayList<String>();
int curPos = 0
;
int prePos = 0
;
for
( char s : formula.toCharArray()) ...{
if
(s == '+'
|| s == '
#' ||
s == '*'
|| s ==
'/')
... {
values.add(Double.parseDouble(formula.substring(prePos, curPos)
.trim()));
operators.add("" + s);
prePos = curPos +
1;
}
curPos++;
}
values.add(Double.parseDouble(formula.substring(prePos).trim()));
char op;
for
(curPos =
operators.size() -
1 ; curPos >= 0; curPos--) ...{
op = operators.get(curPos).charAt(0);
switch
(op) ...{
case '*
':
values.add(curPos, values.get(curPos) * values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
case '/
':
if(values.get(curPos + 1).doubleValue()==0.0
)//除数为零时
values.add(curPos, new Double(getDefaultValue()));
else
values.add(curPos, values.get(curPos) / values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
}
}
for
(curPos =
operators.size() -
1 ; curPos >= 0; curPos--) ...{
op = operators.get(curPos).charAt(0);
switch
(op) ...{
case '+
':
values.add(curPos, values.get(curPos) + values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
case '#
':
values.add(curPos, values.get(curPos) - values.get(curPos + 1));
values.remove(curPos + 1);
values.remove(curPos + 1);
operators.remove(curPos);
break;
}
}
return values.get(0).doubleValue();
}
/** *//**
* 对数字进行四舍五入
* @param dN 要四舍五入的数
* @param decimalPlace 精度
* @param roundMethod 舍去尾数的策略
* 可取值有BigDecimal.ROUND_HALF_UP BigDecimal.ROUND_HALF_DOWN祥见BigDecimal
*/
public
String numberAround(double
dN,int decimalPlace, int roundMethod)...{
BigDecimal bd = new BigDecimal(String.valueOf(dN));
bd = bd.setScale(decimalPlace, roundMethod);
return String.valueOf(bd);
}
/** *//**
* 对给定的字符串进行模式匹配
* @param str 要匹配的字符串
* @param regix 模式
* @return 返回匹配结果,成功为true,否则为false
**/
public
boolean
check(String str,String regix)...{
boolean result=false;
Pattern p=Pattern.compile(regix);
Matcher m =p.matcher(str);
result=m.matches();
return result;
}
}
//:表达式解析-两栈算法.txt
//:Arithmetic.java
package citi;
import java.util.Iterator;
import java.util.Stack;
import java.util.ArrayList;
public class Arithmetic{
//定义操作符,为简单起见,只涉及四则运算,可相应扩充之
static String Operators= "+-*/()# ";
//定义操作符的比较优先级,
//其中1表示前面的操作符优于后面的操作符
// -1表示前面的操作符低于后面的操作符
// 0表示前面的操作符等于后面的操作符
// 2表示前面的操作符不可能与后面的操作符相比较,如果碰到,则表达式有错
//PrecedeList[0][]表示+和+-*/()#这七个操作符相比较的优先级
//PrecedeList[1][]表示-和+-*/()#这七个操作符相比较的优先级
//以此类推
static byte PrecedeList[][]={
{ 1, 1,-1,-1,-1, 1, 1},
{ 1, 1,-1,-1,-1, 1, 1},
{ 1, 1, 1, 1,-1, 1, 1},
{ 1, 1, 1, 1,-1, 1, 1},
{-1,-1,-1,-1,-1, 0, 2},
{ 1, 1, 1, 1, 2, 1, 1},
{-1,-1,-1,-1,-1, 2, 0}};
//定义数据中可能出现的数字和小数点,可以扩展
static String Numbers= "0123456789. ";
private Stack Operator,Operand;
private ArrayList Expression;
public Arithmetic(String inputStr){
Operator=new Stack();
Operator.push( "# ");
Operand=new Stack();
Expression=new ArrayList();
Parse(inputStr);
}
//解析输入的表达式,将操作符和数据分开
//如输入表达式2+3*(32-2)则解析成2 + 3 * ( 32 - 2 )这九个字符串
private void Parse(String instr){
String single;
int temp;
String tempstr= "# ";
for(int i=0;i <instr.length();i++){
single=instr.substring(i,i+1);
//排除非操作符、数字的非法输入,如2+3m
//Operators.indexOf(single)==6排除#
if(Numbers.indexOf(single) <0 && (Operators.indexOf(single) <0 || Operators.indexOf(single)==6)){
System.out.println( "Input have wrong char: "+single);
Expression.clear();
return;
}
//获得前一个输入字符
temp=Expression.size()-1;
if(temp> -1){
tempstr=(String)Expression.get(temp);
}
//排除连续两个操作符的情况,如3**2
if(Operators.indexOf(single)> -1 && temp> -1 && Operators.indexOf(tempstr)> -1){
System.out.println( "Input have wrong format,two Operators are conjoint ");
Expression.clear();
return;
}
//如果当前字符是数字(包括.)而且前一字符也是数字,则将当前字符加到前一字符后面
//其他情况均新添加一个元素
if(Operators.indexOf(single) <0 && temp> -1 && Operators.indexOf(tempstr) <0){
Expression.set(temp,tempstr+single);
}
else{
Expression.add(single);//其他情况均新添加一个元素
}
}
//为了算法处理方便起见,添加特殊字符#
Expression.add( "# ");
}
//比较两个操作符的优先级
private byte Precede(String firstOperator,String secondOperator){
return PrecedeList[Operators.indexOf(firstOperator)][Operators.indexOf(secondOperator)];
}
//对两个数据字符串进行运算
private double Operate(String firstOperand,String Operator,String secondOperand){
if(Operator.equals( "+ ")){
return (Double.parseDouble(firstOperand)+Double.parseDouble(secondOperand));
}
else if(Operator.equals( "- ")){
return (Double.parseDouble(firstOperand)-Double.parseDouble(secondOperand));
}
else if(Operator.equals( "* ")){
return (Double.parseDouble(firstOperand)*Double.parseDouble(secondOperand));
}
else if(Operator.equals( "/ ")){
return (Double.parseDouble(firstOperand)/Double.parseDouble(secondOperand));
}
else{
System.out.println( "Operator is wrong!Can throw a Exception ");
return 0;
}
}
//采用两个栈对接解析后的表达式进行运算
public double Compute(){
if(Expression.isEmpty()){
System.out.println( "Expresion is empty ");
return 0;
}
Iterator it = Expression.iterator();
String single;
String firstOperand,secondOperand;
single=(String)it.next();
while(!(single.equals( "# ") && Operator.peek().equals( "# "))){
if(Operators.indexOf(single) <0){
Operand.push(single);single=(String)it.next();
}
else{
switch(Precede((String)Operator.peek(),single)){
case -1:Operator.push(single);single=(String)it.next();break;
case 0: Operator.pop();single=(String)it.next();break;
case 1:
secondOperand=(String)Operand.pop();
firstOperand=(String)Operand.pop();
Operand.push(String.valueOf(Operate(firstOperand,(String)Operator.pop(),secondOperand)));break;
case 2: System.out.println( "Expression is wrong!Can throw a Exception ");break;
}
}
}
return Double.parseDouble((String)Operand.pop());
}
public static void main(String[] args){
long t1 = System.currentTimeMillis();
Arithmetic t=new Arithmetic(args[0]);
System.out.println(t.Compute());
long t2 = System.currentTimeMillis();
System.out.println( "Time needed: " + (t2 - t1));
}
}
C# code
using System;
using System.Text;
namespace Lentro.Edu.Ch02
{
public class Expression
{
private StackSimple<int> theStack;
public StringBuilder suffix = new StringBuilder();
/**
* 检查该字符是否为括号
*/
private bool isParen(char c)
{
if (c == '{' || c == '[' || c == '(' || c == ')' || c == ']' || c == '}')
return true;
else
return false;
}
/**
* 检查是否为左括号
*/
private bool isLeftParen(char c)
{
if (c == '{' || c == '[' || c == '(')
return true;
else
return false;
}
/**
* 判断指定的操作符是否为 '+' 或者 '-'
*/
private bool isAddOrSub(int oper)
{
return oper == '+' || oper == '-';
}
/**
* 检查是否为数字
*/
private bool isNumber(int ch)
{
return ch >= 48 && ch <= 57;
}
/**
* 检查表达式是否合法
*/
private bool checkExp(String exp)
{
char[] ch = exp.ToCharArray();
StackSimple<int> theStackXInt = new StackSimple<int>(exp.Length / 2);
/**
* 遍历表达式,只处理括号部分
*/
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
if (isParen(c))
{
/**
* 左括号进栈
*/
if (isLeftParen(c))
{
theStackXInt.Push(c);
}
else
{
if (theStackXInt.IsEmpty())
{
return false;
}
int left = theStackXInt.Pop();
switch (c)
{
case '}':
if (left != '{')
return false;
break;
case ']':
if (left != '[')
return false;
break;
case ')':
if (left != '(')
return false;
break;
}
}
}
}
if (theStackXInt.IsEmpty())
{
return true;
}
else
{
return false;
}
}
/**
* 根据当前操作符处理之前在栈中的操作符,当前操作符暂不处理,放入栈中
*/
private void processOper(char oper)
{
while (!theStack.IsEmpty())
{
int currTop = theStack.Pop();
/**
* 如果是左括号,则不予处理,将括号返回进栈
*
* 若得到的操作符,则进一步判断
*/
if (currTop == '(')
{
theStack.Push(currTop);
break;
}
else
{
if (this.isAddOrSub(currTop))
{
if (this.isAddOrSub(oper))
{
this.suffix.Append((char)currTop);
}
else
{
this.theStack.Push(currTop);
break;
}
}
else
{
this.suffix.Append((char)currTop);
break;
}
}
}
/**
* 当前操作符进栈
*/
theStack.Push(oper);
}
/**
* 处理括弧.
*
* 如果为左括弧,直接进栈;
*
* 否则为右括弧,现将这一对括号中的操作符优先处理完
*/
private void processParen(char paren)
{
if (this.isLeftParen(paren))
{
this.theStack.Push(paren);
}
else
{
while (!theStack.IsEmpty())
{
int chx = theStack.Pop();
if (chx == '(')
break;
else
suffix.Append((char)chx);
}
}
}
/**
* 将正确的中缀表达式转为后缀表达式
*/
private void doTrans(String exp)
{
theStack = new StackSimple<int>(exp.Length);
if (this.checkExp(exp))
{
char[] ch = exp.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
switch (c)
{
case '+':
case '-':
case '*':
case '/':
this.processOper(c);
break;
case '(':
case ')':
this.processParen(c);
break;
default:
this.suffix.Append(c);
break;
}
}
while (!this.theStack.IsEmpty())
{
this.suffix.Append((char)this.theStack.Pop());
}
}
}
/**
* 计算表达式
*/
public int clac(String exp)
{
this.doTrans(exp);
String suff = this.suffix.ToString();
StackSimple<int> stack = new StackSimple<int>(suff.Length);
if (suff == null || suff.Length == 0)
{
}
else
{
char[] ch = suff.ToCharArray();
for (int i = 0; i < ch.Length; i++)
{
char c = ch[i];
if (this.isNumber(c))
{
stack.Push(c - 48);
}
else
{
int operand2 = stack.Pop();
int operand1 = stack.Pop();
switch (c)
{
case '+':
stack.Push(operand1 + operand2);
break;
case '-':
stack.Push(operand1 - operand2);
break;
case '*':
stack.Push(operand1 * operand2);
break;
case '/':
stack.Push(operand1 / operand2);
break;
}
}
}
}
return stack.Peep();
}
}
}
其中StackSimple是自己写的一个简单的栈实现
C# code
using System;
namespace Lentro.Edu.Ch02
{
/// <summary>
/// 用于演示栈(LIFO)的内部实现机制
///
/// xfeng/2010-05-07
/// </summary>
public class StackSimple<T>
{
//栈默认的初始容量大小
private const int DEFAULT_SIZE = 10;
private T[] array;
private int index;
/// <summary>
/// 初始化 Stack 类的新实例,该实例为空并且具有默认初始容量。
/// </summary>
public StackSimple()
: this(DEFAULT_SIZE) { }
/// <summary>
/// 初始化 Stack 类的新实例,该实例为空并且具有指定的初始容量。
/// </summary>
/// <param name="size"></param>
public StackSimple(int size)
{
index = -1;
this.array = new T[size];
}
private int _count;
/// <summary>
/// 获取 Stack 中包含的元素数。
/// </summary>
public int Count
{
get { return _count; }
}
/// <summary>
/// 清空栈
/// </summary>
public void Clear()
{
for (int i = 0; i < array.Length; i++)
{
array[i] = default(T);
this.index = -1;
this._count = 0;
}
}
public Boolean IsEmpty()
{
return this._count == 0;
}
/// <summary>
/// 返回位于 Stack 顶部的对象但不将其移除。
/// </summary>
/// <returns>位于 Stack 顶部的 Object。</returns>
public T Peep()
{
return this.index < 0 ? default(T) : this.array[this.index];
}
/// <summary>
/// 移除并返回位于 Stack 顶部的对象。
/// </summary>
/// <returns>从 Stack 的顶部移除的 Object。 </returns>
public T Pop()
{
T obj = this.index < 0 ? default(T) : this.array[this.index];
if (null != obj)
{
this.index--;
this._count--;
//this.array[this.index] = default(T);
}
return obj;
}
/// <summary>
/// 将对象插入 Stack 的顶部。
/// </summary>
public void Push(T obj)
{
if (null != obj)
{
if (this.index >= this.array.Length - 1)
{
T[] temp = new T[this.array.Length * 2];
int count = 0;
foreach (T item in array)
{
temp[count++] = item;
}
this.array = temp;
}
array[++index] = obj;
this._count++;
}
}
}
}
这是那个栈Demo
C#的动态编译,并返回结果
C# code
private void btn_Compute_Click(object sender, EventArgs e)
{
// 声明要计算C#代码,要求必须完整的C#代码
string strCode = @"
using System;
namespace ParseEx
{
public class ParseExC
{
public static double GetValue() //GetValue(int x) //可以带参数
{
return 1+5*8-(Math.Sin(12)*2.5);
}
}
}";
Stopwatch sw = new Stopwatch();
sw.Start();
string strCode = @"
using System;
namespace ParseEx
{
public class ParseExC
{
public static double GetValue()
{"
+ "return " + this.textBox_Text.Text.Trim() + ";" +
@"}
}
}";
CodeDomProvider comp = new CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
StringBuilder codeBuilder = new StringBuilder();
codeBuilder.AppendLine(strCode);
cp.ReferencedAssemblies.Add("System.dll");
cp.GenerateExecutable = false;
cp.GenerateInMemory = true;
CompilerResults cr = comp.CompileAssemblyFromSource(cp, codeBuilder.ToString());
if (cr.Errors.HasErrors)
{
MessageBox.Show("Error!");
}
else
{
Assembly a = cr.CompiledAssembly;
if (a != null)
{
Type t = a.GetType("ParseEx.ParseExC");
if (t != null)
{
// 因为是静态调用,不需要创建实例了
// object mode = a.CreateInstance("Mode");
MethodInfo mi = t.GetMethod("GetValue", BindingFlags.Static | BindingFlags.Public);
if (mi != null)
{
double d = (double)mi.Invoke(null, null);
//double d = (double)mi.Invoke(null, new object[] { 1 }) }); //可以带参数
sw.Stop();
this.label_Result.Text = "Result = " + d.ToString() + "; Time = " + sw.Elapsed.ToString();
//MessageBox.Show("Result = " + d.ToString());
}
}
}
}
}
}
相关文章推荐
- 转化字符串表达式为数学公式并算出结果
- 转化字符串表达式为数学公式并算出结果—实用类
- 转化字符串表达式为数学公式并算出结果
- 转化字符串表达式为数学公式并算出结果
- 转化字符串表达式为数学公式并算出结果
- asp.net字符串的数学表达式计算结果
- 计算字符串数学公式的结果
- asp.net字符串的数学表达式计算结果
- delphi中用算术表达式算出数学结果的方法。
- python3如何将input输入的字符串转化为表达式并计算出结果
- 字符串转化为数学表达式并求值(后缀表达式)
- Java处理数学公式得出结果
- C#中另类自定义公式计算 字符串转换为计算公式,并得出计算结果
- C#中另类自定义公式计算 字符串转换为计算公式,并得出计算结果
- codeforces 616E Sum of Remainders(数学公式转化 较难)
- 计算出用字符串表示的数学表达式的值
- 取得一个字符串表达式的计算结果(实现方法一)
- Android开发学习笔记之通过API接口将LaTex数学函数表达式转化为图片形式
- 关于数学字符串公式的计算
- 使用java去对比2个带数学公式的字符串