您的位置:首页 > 编程语言 > Java开发

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

2009-01-22 19:18 363 查看
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+"'");
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: