import java.util.Scanner;
/*
2012年11月17日 11:34:10
高级计算器
覃唐弢
* example:
{2.2-2/[3-(34-32)+2.3]+2.2}+2.3
* 1.2*{2.2-2/[3-(34-32)+2.3]+2.2}+2.3=6.852727272727273
* */
public class Counter {
public static void main(String[] args) {
String expreStr = null;
System.out.print("请输入计算表达式:");
Scanner in = new Scanner(System.in);
expreStr = in.next();
Expression expr = new Expression(expreStr);
double result = expr.start();
System.out.println(expreStr+"="+result);
}
}
//表达式处理类
class Expression{
private String expreStr="";
private String temp = "";
private int index = 0; //截取字符的下标位置
private int len= 0 ;//表达式长度
private double num1,num2,result;
private char oper;
private OperStack operStack = new OperStack(); //操作符栈
private NumStack numStack = new NumStack(); //操作数栈
public Expression(String expreStr){
this.expreStr = expreStr;
this.len = this.expreStr.length();
}
//主运算
public double start(){
while(index<len){
//判断一个数的最前面的位 不能是小数点 .
if(this.isOper(this.getNextChar())==-1){
System.err.println("小数点不能在一个数的最前面,如[.123]");
System.exit(0);
}
temp+=this.truncate();
char c = temp.toString().toCharArray()[0];
//是操作符 入操作符栈
if(isOper(c)>0){
//是空 则直接入栈
if(this.operStack.isEmpty()){
this.operStack.push(c);
}else{
//当前 操作符是-+/*就去判断优先级 否则直接入栈
if(isOper(c)==1){
//如果栈顶是 ( 则直接入栈 1{-,+} 2{*, /}
if(this.operStack.priority(this.operStack.getTop())!=0){
//判断优先级
//1.1小于等于 栈顶操作符 ---> 计算 完 后 再入栈
//继续判断当前操作符 和 栈顶操作符的优先级
while(!this.operStack.isEmpty()&&this.operStack.priority(c)<=this.operStack.priority(this.operStack.getTop())){
this.operation();
}
}
}else if(isOper(c)==22){ // 是 ) 则运算 ( ) 之间的
//取完后 则计算 栈中剩余的操作符
while(!this.operStack.isEmpty() && isOper(this.operStack.getTop())==1){
this.operation();
}
//此时 把 操作符栈顶 的 ( -->出栈
this.operStack.pop();
}else if(isOper(c)==33){ // 是 ] 则运算 [ ] 之间的
//取完后 则计算 栈中剩余的操作符
while(!this.operStack.isEmpty() && isOper(this.operStack.getTop())==1){
this.operation();
}
//此时 把 操作符栈顶 的 [ -->出栈
this.operStack.pop();
}else if(isOper(c)==44){ // 是 } 则运算 { } 之间的
//取完后 则计算 栈中剩余的操作符
while(!this.operStack.isEmpty() && isOper(this.operStack.getTop())==1){
this.operation();
}
//此时 把 操作符栈顶 的 { -->出栈
this.operStack.pop();
}
//1.2 大于 栈顶操作符 ---> 入栈
if(isOper(c)<=4)
this.operStack.push(c);
}
}else{
//是操作数 入操作数栈
int isManyPoint = 0;
//应该继续判断下一个字符 是否也为数字
while(index<len && (this.isOper(this.getNextChar())==0 || this.isOper(this.getNextChar())==-1)){
//是数字
if(this.isOper(this.getNextChar())==-1){
isManyPoint++;
}
if(isManyPoint>=2){ //如果一个数中有多个小数点 则退出
System.err.println("一个数不能有多个小数点,如[12.23.23]");
System.exit(0);
}
temp+=this.truncate();
}
try{
this.numStack.push(Double.parseDouble(temp));
} catch (Exception e) {
System.err.println("表达式输入不正确!!");
return 0;
}
}
temp="";//清空
}
//取完后 则计算 栈中剩余的操作符
while(!this.operStack.isEmpty()){
this.operation();
}
//操作数 此时 只有一个元素 即结果
return this.numStack.pop();
}
//取出操作数栈顶两个数 和 操作负 并运算 把结果放入操作数栈
public void operation(){
oper = this.operStack.pop();
num1 = this.numStack.pop();
num2 = this.numStack.pop();
result = this.numStack.operation(num1, oper, num2);
//计算完后 把结果放入 操作数栈顶
this.numStack.push(result);
}
//取得字符串[操作符、操作数]
public String truncate(){
return this.expreStr.substring(index++, index);
}
//如果当前是数字 则获取下一个是否也为数字 12
public char getNextChar(){
String temp = this.expreStr.substring(index, index+1);
char c = temp.toCharArray()[0];
return c;
}
//判断是否为操作符
public int isOper(char oper){
switch(oper){
case '-':
case '+':
case '/':
case '*':
return 1;
case '(':
return 2;
case '[':
return 3;
case '{':
return 4;
case ')':
return 22;
case ']':
return 33;
case '}':
return 44;
case '.':
return -1;
default: //是数字
return 0;
}
}
}
//操作符栈
class OperStack{
private char operStack[] = new char[100];
private int index = 0;
//放入操作符
public void push(char oper){
this.operStack[index++] = oper;
}
//弹出栈顶操作符
public char pop(){
return this.operStack[--index];
}
//取得栈顶操作符
public char getTop(){
return this.operStack[index-1];
}
//判断是否为空
public boolean isEmpty(){
if(index<=0)
return true;
return false;
}
//比较操作符的优先级
public int priority(char oper){
switch(oper){
case '-':
case '+':
return 1;
case '/':
case '*':
return 2;
default:
return 0;
}
}
}
//操作数栈
class NumStack{
private double numStack[] = new double[100];
private int index = 0;
//放入操作符
public void push(double num){
this.numStack[index++] = num;
}
//弹出栈顶操作数
public double pop(){
return this.numStack[--index];
}
//取得栈顶操作数
public double getTop(){
return this.numStack[index-1];
}
//判断是否为空
public boolean isEmpty(){
if(index<=0)
return true;
return false;
}
//运算
public double operation(double num1, char oper, double num2){
switch(oper){
case '-':
return num2-num1;
case '+':
return num2+num1;
case '/':
return num2/num1;
case '*':
return num2*num1;
default:
return 0;
}
}
}