计算器基础原理代码(java)

这个博客展示了如何使用Java编写一个简单的表达式求值器,包括处理变量、运算符和逻辑表达式。代码中实现了括号、算术运算、比较操作、逻辑运算以及对变量的赋值等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

import java.util.regex.*;
import java.util.*;
import java.text.*;

public class JEvaluator {
  private String expression ;
  private Map variables;
  private Stack tokens;

  /**
   * @param expression
   */
  public JEvaluator(String expression){
    this.expression = expression.toUpperCase();
    variables=new HashMap();
  }

  public static void main(String[] args)
  {
    JEvaluator r = new JEvaluator("x<=10/z and y=8*z and name<>'CESAR' or birth_date    try{      
      r.setVariable("x",5);
      r.setVariable("y",50);
      r.setVariable("z",8);
      r.setVariable("name","CESAR");
      r.setVariable("birth_date",new Date());
      
      //r.printStack();
      System.out.println("result = " + r.eval());
      r.setExpression("10+3*2^x-10*sin(1-x/y)");
      r.setVariable("x",5.36);
      r.setVariable("y",47);
      System.out.println("result = " + r.eval());

      r.setExpression("10+sin(3^(1/2))");
      System.out.println("result = " + r.eval());
  
    }catch(Exception ex){
      ex.printStackTrace();
      r.printStack();
    }
  }

  /**
   * @param s, the expression to be evaluated
   */
  public void setExpression(String s){
    this.expression = s.toUpperCase(); //case insensitive.
    this.tokens=null;
    this.variables=new HashMap();
  }

  /**
   * @return the current expression
   */
  public String getExpression(){
    return this.expression;
  }

  /**
   * @return String[] array of current variable names
   */
  public String[] getVariables(){
    String[] vars=new String[variables.size()];
    variables.keySet().toArray(vars);
    return vars;
  }

  /**
   * Sets the value of the variables present in the expression.
   * @param var, variable name (case insentive)
   * @param val, value
   */
  public void setVariable(String var, Object val){
    //if(!variables.containsKey(var)) throw Exception("No existe variable " + var);
    variables.put(var.toUpperCase(),val);
  }

  /**
   * Evaluates the current expression, and returns the result Object: double or boolean
   * @return result (double for mathematical expression, and boolean for logical expression)
   * @throws Exception
   */
  public Object eval()throws Exception{
    if(tokens==null) init();
  
    Stack operand=new Stack();
    Token t1=null;
    Token t2 =null;
    Object result = null;
  
    for(Token t: tokens){
      if(t.type!=Token.Type.OPERATOR){
        operand.push(t);
      }else{
        Operator ope = (Operator)t.value();
        t1 = operand.pop();        
  
        if(ope.isUnary()){
          result = ope.eval(evalToken(t1));
        }else{
          t2 = operand.pop();
          result = ope.eval( evalToken(t2),evalToken(t1));
        }
        //System.out.println("Operacion :" + t + " with :" + t2 + " , " + t1 + " =" + result);
        if(result==null)throw new Exception("Null result on intermediate operation.["+ ope + ":" + t1 + ", " + t2+ "]");
  
        operand.push(new Token(result,Token.Type.CONSTANT));
      }
    }
    return operand.pop().value(); //voila the magic result
  }

  private Object evalToken(Token t)throws Exception{
    switch(t.type){
      case VARIABLE:
        Object var = variables.get(t.value());//retrieve variable value
        if(var==null) throw new Exception("Variable '"+t.value() + "' value not set.");
        return var;
      case CONSTANT:
        return t.value();
      default:
        throw new Exception("Unexpected token type ." + t.type);
    }
  }

  private void init()throws Exception{
    if(expression==null) throw new Exception("Not expression set.");
    //creating operators pattern.  you may add other operator patterns too. but take care of not conflicting with others.  
    Pattern p = Pattern.compile("//s*(<=|>=|<>|=|>|<|//*|/|//+|-|//^|//(|//))//s*|//s+(AND|OR)//s+|(SIN|COS)");
    Matcher matcher = p.matcher(expression);
    //initializing variables
    int start = 0;
    int len = expression.length();

    tokens=new Stack();
    Stack temp=new Stack();
    Token token = null;

    //parsing tokens and converting infix expression to postfix stack
    while(matcher.find()){
      String ope = matcher.group();
      //System.out.println("match:" + ope);
      //avoid matching an operator as part of a variable e.g. sintesis
      if(ope.matches("//w+") && (
        matcher.start()>0 && (expression.charAt(matcher.start()-1)+ope).matches("//w+")
        || matcher.end()        continue;
      }
      //parse operand token
      if(matcher.start()>start){
        token =parseToken(expression.substring(start,matcher.start()));      
        addToken(temp, token);        
        //System.out.println("Token:" + token);
      }
      //parse operator token
      token = new Token(Operator.parse(ope.trim()));
      //System.out.println("Token:" + token);
      addToken(temp, token);
      start=matcher.end();
    }
    //parse last operand token
    if(start      token =parseToken(expression.substring(start,len));      
      addToken(temp, token);
    }
    //ending tokens stack builder
    while(!temp.empty()){
      Token t = temp.pop();
      if(t.inputPriority()==t.stackPriority()) //exclude brackets
        tokens.push(t);
    }
  }

  protected Token parseToken(String val)throws Exception{
      //analize token: constant?, variable?
      Token.Type type = null;
      Object obj=null;
  
      if(val.matches("'[^']*'")){//string constant
        type=Token.Type.CONSTANT;
        obj=val.substring(1,val.length()-1);
      }else if(val.matches("DATE//'//d{2,2}//,//d{2,2}//,//d{4,4}//'")){//date constant
        type=Token.Type.CONSTANT;
        SimpleDateFormat sdf = new SimpleDateFormat("dd,MM,yyyy");
        obj=sdf.parse(val.substring(6,val.length()-1));
      }else if(val.matches("//d*//.?//d*")){//numeric
        type=Token.Type.CONSTANT;
        obj= Double.parseDouble(val);
      }else if(val.matches("//w+")){//variable
        if(!variables.containsKey(val))variables.put(val,null);
        type=Token.Type.VARIABLE;
        obj=val;
      }else{
        throw new Exception("token not recognized: " + val);
      }
      return new Token(obj,type);
  }

  private void addToken(Stack temp, Token t){
    //applying infix to postfix conversion algorithm
    while(!temp.empty() && t.inputPriority()<=temp.peek().stackPriority()){
      Token t1=temp.pop();
      if(t1.inputPriority()==t1.stackPriority()){ //exclude brackets
        tokens.push(t1);
      }        
    }
    //pushing the token
    temp.push(t);
  }

  /**
   * prints to standard output the tokens stack.
   */
  public void printStack(){
    for(Token t: tokens){
      System.out.println(t);
    }
  }
}

/**
* Represents a token of the expression
*/
class Token
{
  public enum Type{VARIABLE,CONSTANT,OPERATOR};  
  private Object value;
  public Type type;
  
  /**
   * @param val
   * @param type
   */
  public Token(Object val, Type type){
    this.value=val;
    this.type=type;
  }
  /**
   * @param ope
   */
  public Token(Operator ope){
    this.value=ope;
    this.type=Type.OPERATOR;
  }

  /**
   * @return
   */
  int inputPriority(){
    if(type==Type.OPERATOR) return ((Operator)value).inputPriority();
    else return Operator.LAST_PRIORITY;
  }

  /**
   * @return
   */
  int stackPriority(){
    if(type==Type.OPERATOR) return ((Operator)value).stackPriority();
    else return Operator.LAST_PRIORITY;
  }

  /**
   * @return
   */
  public Object value(){
    return this.value;
  }

  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  public String toString(){
    return type + ":" + value;
  }

};

//operator types: * / + - = < > <= >= & |
/**
* Represents each operation implemented for the evaluator.
*/
enum Operator{
  SIN("SIN",25,true){Object eval(Object... args){return Math.sin(((Number)args[0]).doubleValue());} },
  COS("COS",25,true){Object eval(Object... args){return Math.cos(((Number)args[0]).doubleValue());} },
  TAN("TAN",25,true){Object eval(Object... args){return Math.tan(((Number)args[0]).doubleValue());} },
  EXP("^",23){Object eval(Object... args){return Math.pow(((Number)args[0]).doubleValue(),((Number)args[1]).doubleValue());} },
  PROD("*",20){Object eval(Object... args){return ((Number)args[0]).doubleValue()*((Number)args[1]).doubleValue();} },
  DIV("/",20){Object eval(Object... args){return ((Number)args[0]).doubleValue()/((Number)args[1]).doubleValue();} },
  SUM("+",15){Object eval(Object... args){return ((Number)args[0]).doubleValue()+((Number)args[1]).doubleValue();} },
  DIF("-",15){Object eval(Object... args){return ((Number)args[0]).doubleValue()-((Number)args[1]).doubleValue();} },
  EQL("=",10){Object eval(Object... args){return args[0].equals(args[1]);} },
  NEQL("<>",10){Object eval(Object... args){return !args[0].equals(args[1]);} },
  LT("<",10){Object eval(Object... args){
    if(args[0] instanceof Number) return ((Number)args[0]).doubleValue()<((Number)args[1]).doubleValue();
    else return ((Comparable)args[0]).compareTo(args[1])<0;} },
  GT(">",10){Object eval(Object... args){
    if(args[0] instanceof Number) return ((Number)args[0]).doubleValue()>((Number)args[1]).doubleValue();
    else return ((Comparable)args[0]).compareTo(args[1])>0;} },
  LTEQ("<=",10){Object eval(Object... args){
    if(args[0] instanceof Number) return ((Number)args[0]).doubleValue()<=((Number)args[1]).doubleValue();
    else return ((Comparable)args[0]).compareTo(args[1])<=0;} },
  GTEQ(">=",10){Object eval(Object... args){
    if(args[0] instanceof Number) return ((Number)args[0]).doubleValue()>=((Number)args[1]).doubleValue();
    else return ((Comparable)args[0]).compareTo(args[1])>=0;} },
  AND("AND",5){Object eval(Object... args){return (Boolean)args[0] && (Boolean)args[1];}},
  OR("OR",2){Object eval(Object... args){return ((Boolean)args[0] || (Boolean)args[1]);}},
  BRAKET_OPEN("(",30,1){Object eval(Object... args){return null;}},
   BRAKET_CLOSE(")",1,30){Object eval(Object... args){return null;}};

  public static final int LAST_PRIORITY=30;    
  private final int inputPriority;//prioridad
  private final int stackPriority;
  private final String symbol;
  private boolean unary=false;

  /**
   * @return the operator input priority
   */
  int inputPriority(){return inputPriority;}
  int stackPriority(){return stackPriority;}
  String symbol(){return symbol;}
  boolean isUnary(){return unary;}

  private Operator(String symbol,int prio){
    this.inputPriority=prio;
    this.stackPriority=prio;
    this.symbol=symbol;
  }
  private Operator(String symbol,int prio, boolean unary){
    this.inputPriority=prio;
    this.stackPriority=prio;
    this.symbol=symbol;
    this.unary=unary;
  }
  private Operator(String symbol,int inprio, int stackprio){
    this.inputPriority=inprio;
    this.stackPriority=stackprio;
    this.symbol=symbol;
  }

  abstract Object eval(Object... args);

  public static Operator parse(String s)throws Exception{
    for(Operator o:Operator.values()){
      if(o.symbol().equals(s)){
        return o;
      }
    }
    throw new Exception("Operator not recognized '"+s+"'");
  }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值