如何用Java 实现 Excel 表达式的解析(摘自:http://topic.csdn.net/t/20030408/17/1634982.html#)
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;   
  }   
    
    
  }   
                    
                
                
            
        
浙公网安备 33010602011771号