高分求解:如何用Java 实现 Excel 表达式的解析? 就是Java获取这么一个表达式后,如何进行解析并得出计算结果?多谢! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 建议参考编译原理方面的资料。对于四则运算可以参考下面的代码,当然也可以扩展到其他运算://:表达式解析-两栈算法.txt//:Arithmetic.javapackage 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)); }}运行:F:\java>javac Arithmetic.java -d .F:\java>java citi.Arithmetic 3*(34+4*4)150.0Time needed: 10 虽然我还没有看懂,不过我想这个算法好像只能解决简单的运算问题,不过还是要感谢tangshancheng!各位大虾,有没有更好的? 估计不会太难,在编译原理的书有很多例子可以这样考虑使用递归求解.先做一个简单的if求解过程.再设定一个递归结束条件.在清华的数据结构(c++)上有现成的例子. 我觉得没必要写个运算器吧,可不可以这样,Excel的表达式让excel去解释,java只取其结果,excel的运算必然会写到一个格中去吧,就在那儿取结果不更省事吗,不知楼主的意思是不是这样... Jakarta POI 可以很方便的解决 我花了些时间终于完成了这么一个烂东西,解决方法可能不是很优化,不过也发布出来让大家参考参考,如果各位大虾有更好的解决方案,还请mail给我:[email protected] java.util.*;public class Calculator{ public Calculator(){ } /* public Calculator(String data) { bits = data.toCharArray(); } */ /** * 计算 * @return double类型的计算结果 * @throws ArithmeticException 计算出现错误 * @throws NumberFormatException 数据格式错误 */ public double evaluate(String data) throws ArithmeticException, NumberFormatException { if(data.toLowerCase().indexOf("if")>=0) data = evalIfFunction(data); bits = data.toCharArray(); pos = 0; double ret = evalPlusMinus(); if (pos != bits.length) { throw new NumberFormatException("Garbage at end of equation"); } return ret; } public double evaluate(double x, String data) throws ArithmeticException, NumberFormatException { this.x = x; return evaluate(data); } private void skipWS() { while ((pos < bits.length) && Character.isWhitespace(bits[pos])) { pos++; } } private double evalReal() throws NumberFormatException { skipWS(); int save = pos; while ((pos < bits.length) && Character.isDigit(bits[pos])) { pos++; } if ((pos == save) && (bits[pos] != '.')) { throw new NumberFormatException("pos != save"); } if ((pos < bits.length) && bits[pos] == '.') { int saved = ++pos; while ((pos < bits.length) && Character.isDigit(bits[pos])) { pos++; } if (pos == saved) { throw new NumberFormatException("Invalid numeric literal"); } } return Double.valueOf(new String(bits, save, pos-save)).doubleValue(); } private double evalSymbol() throws ArithmeticException, NumberFormatException { double lhs = 0.0; int skip = pos; while ((skip < bits.length)&& Character.isLetterOrDigit(bits[skip])) { skip++; } if (skip > pos) { String symbol = new String(bits, pos, skip-pos); if (symbol.equals("pi")) { lhs = Math.PI; } else if (symbol.equals("e")) { lhs = Math.E; } else if (symbol.equals("x")) { lhs = x; } else { throw new NumberFormatException("Unknown symbol: " + symbol); } pos = skip; } return lhs; } private double evalFunction() throws ArithmeticException, NumberFormatException, SymbolNotFoundException { double lhs = 0.0; int skip = pos; while ((skip < bits.length)&& Character.isLetterOrDigit(bits[skip])) { skip++; } if (skip > pos) { String symbol = new String(bits, pos, skip-pos); int saved = pos; pos = skip; if (symbol.equals("sin")) { lhs = Math.sin(evalTerm()); } else if (symbol.equals("cos")) { lhs = Math.cos(evalTerm()); } else if (symbol.equals("tan")) { lhs = Math.tan(evalTerm()); } else if (symbol.equals("asin")) { lhs = Math.asin(evalTerm()); } else if (symbol.equals("acos")) { lhs = Math.acos(evalTerm()); } else if (symbol.equals("atan")) { lhs = Math.atan(evalTerm()); } else if (symbol.equals("ln")) { lhs = Math.log(evalTerm()); } else if (symbol.equals("deg")) { lhs = Math.toDegrees(evalTerm()); } else if (symbol.equals("rad")) { lhs = Math.toRadians(evalTerm()); } else{ pos = saved; throw new SymbolNotFoundException(); } if (Double.isNaN(lhs)) { throw new ArithmeticException(symbol + ": Invalid Domain"); } } return lhs; } private double evalTerm() throws ArithmeticException, NumberFormatException { double lhs = 0.0; skipWS(); switch (bits[pos]) { case '(': pos++; lhs = evalPlusMinus(); skipWS(); if ((pos < bits.length) && (bits[pos] == ')')) { pos++; } else { throw new NumberFormatException("Missing ')' in expression"); } break; case '[': pos++; lhs = evalPlusMinus(); skipWS(); if ((pos < bits.length) && (bits[pos] == ']')) { pos++; } else { throw new NumberFormatException("Missing ']' in expression"); } break; default: if (Character.isDigit(bits[pos]) || (bits[pos] == '.')) { lhs = evalReal(); } else if (Character.isLetter(bits[pos])) { try { lhs = evalFunction(); } catch (SymbolNotFoundException sym) { lhs = evalSymbol(); } } else { throw new NumberFormatException("Expecting Term"); } break; } return lhs; } private double evalUnary() throws ArithmeticException, NumberFormatException { double lhs = 0.0; skipWS(); if (pos >= bits.length) { throw new NumberFormatException("Premature expression end"); } switch (bits[pos]) { case '-': pos++; lhs = -evalUnary(); break; case '+': pos++; lhs = evalUnary(); break; default: lhs = evalTerm(); break; } return lhs; } private double evalExponent() throws ArithmeticException, NumberFormatException { double lhs = evalUnary(); boolean need_more = true; skipWS(); while ((pos < bits.length) && need_more) { switch (bits[pos]) { case '^': pos++; lhs = Math.pow(lhs, evalUnary()); break; case '!': int lhs_int = (int)lhs; pos++; if (lhs < 0 || lhs_int != lhs) { throw new ArithmeticException("Invalid domain"); } lhs = 1.0; for(int i = 2; i <= lhs_int; i++) { lhs *= i; } break; case '%': pos++; lhs /= 100; break; default: need_more = false; break; } } return lhs; } private double evalMultDivide() throws ArithmeticException, NumberFormatException { double lhs = evalExponent(); boolean need_more = true; skipWS(); while ((pos < bits.length) && need_more) { switch (bits[pos]) { case '*': pos++; lhs *= evalExponent(); break; case '/': pos++; lhs /= evalExponent(); break; default: need_more = false; break; } } return lhs; } private double evalPlusMinus() throws ArithmeticException, NumberFormatException { double lhs = evalMultDivide(); boolean need_more = true; skipWS(); while ((pos < bits.length) && need_more) { switch (bits[pos]) { case '-': pos++; lhs -= evalMultDivide(); break; case '+': pos++; lhs += evalMultDivide(); break; default: need_more = false; break; } } return lhs; } private char bits[]; private int pos = 0; private double x = 0.0; private int ifPos = 0;#太长了...,再来一贴... #续上贴....private String evalIfFunction(String express) throws ArithmeticException, NumberFormatException{ int lastIfPos = express.lastIndexOf("if"); if(lastIfPos<0) return express; ifPos = lastIfPos; String beforeIf = express.substring(0,lastIfPos); String afterIf = express.substring(ifPos); bits = afterIf.toCharArray(); double ifValue = evalLastIf(); String nonIfString = beforeIf + String.valueOf(ifValue) + afterIf.substring(ifPos); express = evalIfFunction(nonIfString); return express; } private double evalLastIf() throws ArithmeticException, NumberFormatException{ double x = 0.0; skipWS(); int skip = 0; String compareExpress=null; String trueTerm=null; String falseTerm=null; while((skip<bits.length) && bits[skip]!=','){ skip++; } if(skip>0){ compareExpress = new String(bits, 3, skip-3); } //get the true expression skip++; ifPos = skip; while( (skip<bits.length)&& bits[skip]!=','){ skip++; } if(skip>pos){ trueTerm = new String(bits, ifPos, skip-ifPos); ifPos = skip; } //get the false expression skip++; ifPos = skip; int leftBracket = 0; int rightBracket = 0; while((skip<bits.length) && bits[skip]!=')'){ if(bits[skip]=='('){ leftBracket ++; } skip++; } while(rightBracket<leftBracket+1){ if(bits[skip]==')'){ rightBracket++; } skip++; } if(skip>ifPos){ falseTerm = new String(bits, ifPos, skip-ifPos-1); ifPos = skip; } boolean compare = evalCompare(compareExpress); if(compare){ x = this.evaluate(trueTerm); }else{ x = this.evaluate(falseTerm); } return x; } private boolean evalCompare(String express) throws ArithmeticException, NumberFormatException { boolean isTrue = false; char[] ifBits = express.toCharArray(); String partA = null; String partB = null; String compareType = null; int i = 0; int skip = 0; while(skip<ifBits.length && !isCompareFlag(ifBits[skip])){ skip++; } partA = new String(ifBits, i, skip); i = skip; if(ifBits[skip+1]!='='){ compareType = new String(ifBits,skip,1); partB = new String(ifBits,++skip,ifBits.length - skip); }else{ compareType = new String(ifBits, skip, 2); partB = new String(ifBits, skip+2, ifBits.length - skip-2); } double a = this.evaluate(partA); double b = this.evaluate(partB); if(compareType.length()==1){ char[] compareChar = compareType.toCharArray(); switch(compareChar[0]){ case '>': return (a>b); case '<': return (a<b); case '=': return (a==b); default: return false; } }else{ if(compareType.equals(">=")){ return (a>b || a==b); }else if(compareType.equals("<=")){ return (a<b || a==b); } } return isTrue; } private boolean isCompareFlag(char c){ boolean isCompare = false; switch(c){ case '>': return true; case '<': return true; case '=': return true; } return false; }} 新人求解。关与Java枚举错误 js解析本地txt的完整实例 如何在JSP里调用DLL 还是这个问题,问了好多人了也没懂,所以另起一页。 请问大家几个好的JAVA源代码下载网站 关于Java使用Access的问题 serverlet.jar如何解压? 是jdk的bug吗? 关于方法调用的问题! weblogic6。0下怎样连接数据库? 如何初始化一个xml的dom树 急:怎样手工调用事件方法?
//:表达式解析-两栈算法.txt
//:Arithmetic.javapackage 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));
}
}运行:
F:\java>javac Arithmetic.java -d .F:\java>java citi.Arithmetic 3*(34+4*4)
150.0
Time needed: 10
各位大虾,有没有更好的?
可以这样考虑使用递归求解.
先做一个简单的if求解过程.
再设定一个递归结束条件.
在清华的数据结构(c++)上有现成的例子.
public class Calculator
{ public Calculator(){ }
/*
public Calculator(String data)
{
bits = data.toCharArray();
}
*/
/**
* 计算
* @return double类型的计算结果
* @throws ArithmeticException 计算出现错误
* @throws NumberFormatException 数据格式错误
*/
public double evaluate(String data)
throws ArithmeticException, NumberFormatException
{
if(data.toLowerCase().indexOf("if")>=0)
data = evalIfFunction(data);
bits = data.toCharArray();
pos = 0;
double ret = evalPlusMinus(); if (pos != bits.length) {
throw new NumberFormatException("Garbage at end of equation");
} return ret;
}
public double evaluate(double x, String data)
throws ArithmeticException, NumberFormatException
{
this.x = x;
return evaluate(data);
} private void skipWS()
{
while ((pos < bits.length) && Character.isWhitespace(bits[pos])) {
pos++;
}
} private double evalReal() throws NumberFormatException
{
skipWS();
int save = pos; while ((pos < bits.length) && Character.isDigit(bits[pos])) {
pos++;
} if ((pos == save) && (bits[pos] != '.')) {
throw new NumberFormatException("pos != save");
} if ((pos < bits.length) && bits[pos] == '.') {
int saved = ++pos; while ((pos < bits.length) && Character.isDigit(bits[pos])) {
pos++;
} if (pos == saved) {
throw new NumberFormatException("Invalid numeric literal");
}
} return Double.valueOf(new String(bits, save, pos-save)).doubleValue();
} private double evalSymbol()
throws ArithmeticException, NumberFormatException
{
double lhs = 0.0;
int skip = pos; while ((skip < bits.length)&& Character.isLetterOrDigit(bits[skip])) {
skip++;
} if (skip > pos) {
String symbol = new String(bits, pos, skip-pos); if (symbol.equals("pi")) {
lhs = Math.PI;
} else if (symbol.equals("e")) {
lhs = Math.E;
} else if (symbol.equals("x")) {
lhs = x;
} else {
throw new NumberFormatException("Unknown symbol: " + symbol);
}
pos = skip;
} return lhs;
}
private double evalFunction()
throws ArithmeticException, NumberFormatException,
SymbolNotFoundException
{
double lhs = 0.0;
int skip = pos; while ((skip < bits.length)&& Character.isLetterOrDigit(bits[skip])) {
skip++;
} if (skip > pos) {
String symbol = new String(bits, pos, skip-pos);
int saved = pos; pos = skip; if (symbol.equals("sin")) {
lhs = Math.sin(evalTerm());
} else if (symbol.equals("cos")) {
lhs = Math.cos(evalTerm());
} else if (symbol.equals("tan")) {
lhs = Math.tan(evalTerm());
} else if (symbol.equals("asin")) {
lhs = Math.asin(evalTerm());
} else if (symbol.equals("acos")) {
lhs = Math.acos(evalTerm());
} else if (symbol.equals("atan")) {
lhs = Math.atan(evalTerm());
} else if (symbol.equals("ln")) {
lhs = Math.log(evalTerm());
} else if (symbol.equals("deg")) {
lhs = Math.toDegrees(evalTerm());
} else if (symbol.equals("rad")) {
lhs = Math.toRadians(evalTerm());
} else{
pos = saved;
throw new SymbolNotFoundException();
} if (Double.isNaN(lhs)) {
throw new ArithmeticException(symbol + ": Invalid Domain");
}
} return lhs;
} private double evalTerm()
throws ArithmeticException, NumberFormatException
{
double lhs = 0.0;
skipWS(); switch (bits[pos]) {
case '(':
pos++;
lhs = evalPlusMinus();
skipWS();
if ((pos < bits.length) && (bits[pos] == ')')) {
pos++;
} else {
throw new NumberFormatException("Missing ')' in expression");
}
break;
case '[':
pos++;
lhs = evalPlusMinus();
skipWS();
if ((pos < bits.length) && (bits[pos] == ']')) {
pos++;
} else {
throw new NumberFormatException("Missing ']' in expression");
}
break; default:
if (Character.isDigit(bits[pos]) || (bits[pos] == '.')) {
lhs = evalReal();
} else if (Character.isLetter(bits[pos])) {
try {
lhs = evalFunction();
} catch (SymbolNotFoundException sym) {
lhs = evalSymbol();
}
} else {
throw new NumberFormatException("Expecting Term");
}
break;
} return lhs;
}
private double evalUnary()
throws ArithmeticException, NumberFormatException
{
double lhs = 0.0;
skipWS(); if (pos >= bits.length) {
throw new NumberFormatException("Premature expression end");
} switch (bits[pos]) {
case '-':
pos++;
lhs = -evalUnary();
break;
case '+':
pos++;
lhs = evalUnary();
break;
default:
lhs = evalTerm();
break;
} return lhs;
} private double evalExponent()
throws ArithmeticException, NumberFormatException
{
double lhs = evalUnary();
boolean need_more = true;
skipWS(); while ((pos < bits.length) && need_more) {
switch (bits[pos]) {
case '^':
pos++;
lhs = Math.pow(lhs, evalUnary());
break;
case '!':
int lhs_int = (int)lhs;
pos++; if (lhs < 0 || lhs_int != lhs) {
throw new ArithmeticException("Invalid domain");
} lhs = 1.0;
for(int i = 2; i <= lhs_int; i++) {
lhs *= i;
}
break;
case '%':
pos++;
lhs /= 100;
break;
default:
need_more = false;
break;
}
} return lhs;
} private double evalMultDivide()
throws ArithmeticException, NumberFormatException
{
double lhs = evalExponent();
boolean need_more = true;
skipWS(); while ((pos < bits.length) && need_more) {
switch (bits[pos]) {
case '*':
pos++;
lhs *= evalExponent();
break;
case '/':
pos++;
lhs /= evalExponent();
break;
default:
need_more = false;
break;
}
} return lhs;
} private double evalPlusMinus()
throws ArithmeticException, NumberFormatException
{
double lhs = evalMultDivide();
boolean need_more = true;
skipWS(); while ((pos < bits.length) && need_more) {
switch (bits[pos]) {
case '-':
pos++;
lhs -= evalMultDivide();
break;
case '+':
pos++;
lhs += evalMultDivide();
break;
default:
need_more = false;
break;
}
} return lhs;
} private char bits[];
private int pos = 0;
private double x = 0.0; private int ifPos = 0;#太长了...,再来一贴...
private String evalIfFunction(String express) throws ArithmeticException, NumberFormatException{
int lastIfPos = express.lastIndexOf("if");
if(lastIfPos<0) return express; ifPos = lastIfPos;
String beforeIf = express.substring(0,lastIfPos);
String afterIf = express.substring(ifPos);
bits = afterIf.toCharArray();
double ifValue = evalLastIf(); String nonIfString = beforeIf + String.valueOf(ifValue) + afterIf.substring(ifPos);
express = evalIfFunction(nonIfString);
return express; }
private double evalLastIf() throws ArithmeticException, NumberFormatException{
double x = 0.0;
skipWS();
int skip = 0;
String compareExpress=null;
String trueTerm=null;
String falseTerm=null; while((skip<bits.length) && bits[skip]!=','){
skip++;
}
if(skip>0){
compareExpress = new String(bits, 3, skip-3);
}
//get the true expression
skip++;
ifPos = skip;
while( (skip<bits.length)&& bits[skip]!=','){
skip++;
}
if(skip>pos){
trueTerm = new String(bits, ifPos, skip-ifPos);
ifPos = skip;
}
//get the false expression
skip++;
ifPos = skip;
int leftBracket = 0;
int rightBracket = 0;
while((skip<bits.length) && bits[skip]!=')'){
if(bits[skip]=='('){
leftBracket ++;
}
skip++;
}
while(rightBracket<leftBracket+1){
if(bits[skip]==')'){
rightBracket++;
}
skip++;
}
if(skip>ifPos){
falseTerm = new String(bits, ifPos, skip-ifPos-1);
ifPos = skip;
} boolean compare = evalCompare(compareExpress);
if(compare){
x = this.evaluate(trueTerm);
}else{
x = this.evaluate(falseTerm);
}
return x;
}
private boolean evalCompare(String express) throws ArithmeticException, NumberFormatException {
boolean isTrue = false;
char[] ifBits = express.toCharArray();
String partA = null;
String partB = null;
String compareType = null; int i = 0;
int skip = 0;
while(skip<ifBits.length && !isCompareFlag(ifBits[skip])){
skip++;
}
partA = new String(ifBits, i, skip);
i = skip; if(ifBits[skip+1]!='='){
compareType = new String(ifBits,skip,1);
partB = new String(ifBits,++skip,ifBits.length - skip);
}else{
compareType = new String(ifBits, skip, 2);
partB = new String(ifBits, skip+2, ifBits.length - skip-2);
}
double a = this.evaluate(partA);
double b = this.evaluate(partB);
if(compareType.length()==1){
char[] compareChar = compareType.toCharArray();
switch(compareChar[0]){
case '>':
return (a>b);
case '<':
return (a<b);
case '=':
return (a==b);
default:
return false;
}
}else{
if(compareType.equals(">=")){
return (a>b || a==b);
}else if(compareType.equals("<=")){
return (a<b || a==b);
}
} return isTrue;
}
private boolean isCompareFlag(char c){
boolean isCompare = false;
switch(c){
case '>':
return true;
case '<':
return true;
case '=':
return true;
}
return false;
}
}