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

用Java写的一个实现大数计算器的类

2014-01-22 20:56 120 查看
为了练习一下Java编程,今天写了一个能进行大数计算的类,只需要调用本类的一个方法,以算数表达式为参数,方法就可返回计算结果。

import java.math.BigInteger;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.Stack;

/*
* 该类实现对大值数进行简单计算的功能
* */
class BigNumCalculator {

private String input; //要计算的表达式
private String output;//结算结果
Stack<BigInteger> operand;//操作数栈
Stack<String> operator;//操作符栈
HashMap<String, Integer> prect_map; //操作符和优先级之间的映射关系

/*
* 无参构造函数
* */
public BigNumCalculator() {
this.operand = new Stack<BigInteger>();
this.operator = new Stack<String>();
prect_map = new HashMap<String, Integer>();
prect_map.put("+", new Integer(1));
prect_map.put("-", new Integer(1));
prect_map.put("*", new Integer(2));
prect_map.put("/", new Integer(2));
}

/*
* 对输入的表达式进行简单的检查。合法字符:数字、+、-、*、/、(、)之外是否还包含别的字符)
* 返回值:如果表达式不包含非合法字符,则返回true,否则返回false
* 调用本类函数:无
* */
private void check()throws ExpressionException {
if(!this.input.matches("[\\d\\+\\-\\*/()]*"))//用正则表达式检查表达式是否合法,如果不合法,抛出表达式不合法异常,不懂正则表达式的参考此处:点击打开链接
throw new ExpressionException("Expressions contain only numbers,+,-,*,/");
}

/*
* 函数功能:比较两个操作符的优先级
* 参数:要比较的两个操作符
* 返回值:如果1、第一个操作符优先级比第二个低,返回负值;
* 			2、优先级相同,返回0;
* 			3、第一个操作符比第二个操作符高,返回正值
* 调用本类函数:无
* */
private int compOperator(String op1, String op2) {
return this.prect_map.get(op1).intValue() - this.prect_map.get(op2).intValue();
}

/*
* 函数功能:将两个指定的大数对象,按指定的操作符进行运算,得出结果
* 参数:要计算的两个大数类对象,和字符串表示的操作符
* 返回值:返回一个大整数类对象,表示操作结果
* 调用本类函数:无
* */
private BigInteger compute(BigInteger bi1, BigInteger bi2, String operator) {
switch(operator.charAt(0)) {

case '+': return bi1.add(bi2);
case '-': return bi1.subtract(bi2);
case '*': return bi1.multiply(bi2);
case '/': return bi1.divide(bi2);
default: return null;
}
}

/*
* 函数功能:根据输入的表达式,计算出用字符串表示的结果
* 参数:一个String对象,表示要计算的表达式
* 返回值:一个String对象,表示结算得到的结果
* 异常抛出:如果表达式不合法,则抛出相应的异常
* 调用本类中的函数:check(),compOperator(),compute()
* */
public String calculate(String input) throws ExpressionException{

input = "(" + input + ")";//将传进来的表达式字符串赋值给类成员,之所以给表达式包上一层括号,上为了方便最后得到一个结果
this.input = input;

this.check(); //检查表达式是否合法

StringBuffer sb = new StringBuffer();	//解析表达式时用来存储数字
for(int j = 0; j < input.length(); j ++) {
String tmp = "" + input.charAt(j);//将当前正解析的字符转化为字符串

if(tmp.matches("\\d")) {//当前解析的是数字
sb.append(tmp.charAt(0));
}
else if(tmp.charAt(0) == '(') {//当前解析的是'('
//(前面必定紧挨着操作符,所以不需要将操作数进行压栈,因为StringBuffer对象必为空
this.operator.push(tmp);
}
else if(tmp.matches("[\\+\\-\\*/]{1}")) {//当前解析的是+、-、*、/

//遇到操作符,将之前的字符串变换为一个大数,压入操作数栈中,并将存储数字的StringBuffer对象清空
BigInteger biTemp = new BigInteger(sb.toString());
this.operand.push(biTemp);
sb.delete(0, sb.length());

/*执行操作符栈中优先级低于或等于当前操作符的操作
* 首先从操作符栈中弹出一个操作符,
* 然后从操作数栈中弹出两个操作数
* 执行操作后将结果压入操作数栈中
* */
while(!this.operator.empty()) {
String topOperator = this.operator.pop();
if(topOperator.equals("(")) {//如果遇到"(",停止处理
this.operator.push(topOperator);
break;
}
if(this.compOperator(tmp, topOperator) <= 0) {//如果栈中的操作符优先级比当前解析的操作符优先级高或相等
BigInteger bi1 = this.operand.pop();
BigInteger bi2 = this.operand.pop();
this.operand.push(this.compute(bi1, bi2, topOperator));
}
else {//如果栈中的操作符比当前解析的操作符优先级低
this.operator.push(topOperator);//将弹出的操作符重新压入操作符栈
break;
}
}
this.operator.push(tmp);//将当前操作符压入操作符栈
}
else {//如果当前解析的右括号)
//将之前的字符串变换为一个大数,压入操作数栈中,并将存储数字的StringBuffer对象清空
BigInteger biTemp = new BigInteger(sb.toString());
this.operand.push(biTemp);
sb.delete(0, sb.length());

try {
String topOperator = this.operator.pop();
while(!topOperator.equals("(")) {
BigInteger bi1 = this.operand.pop();
BigInteger bi2 = this.operand.pop();
this.operand.push(this.compute(bi1, bi2, topOperator));
topOperator = this.operator.pop();
}
}
catch(EmptyStackException e) {
throw new ExpressionException();
}
}
}
if(!this.operator.empty() || this.operand.size() != 1)
throw new ExpressionException();
this.output = this.operand.pop().toString();
return this.output;
}

}


上面的类中引用了自己编写的一个异常类:

/*
* 自己编写的一个异常类,如果表达式不合法,则抛出该异常
* */
class ExpressionException extends Exception {

/**
*
*/
private static final long serialVersionUID = 1L;

public ExpressionException(String msg) {
super(msg);
}

public ExpressionException() {
super("parsing fault");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: