qjlyp

qjlyp

导航

如何用Java 实现 Excel 表达式的解析(摘自:http://topic.csdn.net/t/20030408/17/1634982.html#)

import   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;  
  }  
   
   
  }  

posted on 2008-10-27 14:00  qjlyp  阅读(433)  评论(0编辑  收藏  举报