最近上网查了一下,竟然没有找到用Java编写的四则运算的代码,就小写了一下.如有问题请大家反馈.
1.说明
代码只是实现了简单的四则运算,支持+,-,*,/,(,) 只能计算出正确的表达式的值,没有对非法表达式进行校验.
2.实现方法
第一步:将输入的字符串转换为List,主要是用来将String转换为原子:数值/运算符/括号
public List transStr(String str)
{
List strList = new ArrayList();
String tmp = str.replaceAll("\d*", "");
String curLet = null;
int loc = 0;
int len = tmp.length();
for (int i = 0; i < len; i++)
{
curLet = tmp.substring(i, i + 1);
loc = str.indexOf(curLet);
if (!"".equals(str.substring(0, loc).trim()))
{
strList.add(str.substring(0, loc).trim());
}
strList.add(str.substring(loc, loc + 1));
str = str.substring(loc + 1);
}
if (0 < str.length())
{
strList.add(str.trim());
}
return strList;
}
第二步: 将原来的中缀表达式转换为后缀表达式,在四则运算中,后缀表达式是最方便计算的
public String[] midToEnd(List midList)
{
Stack embl = new Stack();
Stack result = new Stack();
Iterator it = midList.iterator();
String curStr = null;
while (it.hasNext())
{
curStr = (String) it.next();
if(sign.containsKey(curStr))
{
if (0 == embl.size() || "(".equals(curStr))
{
embl.push(curStr);
}
else
{
if(")".equals(curStr))
{
while(!"(".equals((String)embl.peek()))
{
if(0 >= embl.size())
{
return null;
}
result.push(embl.pop());
}
embl.pop();
}
else
{
int p1 = Integer.parseInt((String) sign.get(curStr));
int p2 = Integer.parseInt((String) sign.get(embl.peek()));
if (p1 > p2)
{
embl.push(curStr);
}
else
{
while (p1 <= p2 || embl.size() > 0)
{
result.push(embl.pop());
if(0 == embl.size())
{
break;
}
p2 = Integer.parseInt((String) sign.get(embl.peek()));
}
embl.push(curStr);
}
}
}
}
else
{
result.push(curStr);
}
}
while (0 < embl.size())
{
result.push(embl.pop());
}
int len = result.size();
String[] ret = new String[len];
for (int i = 0; i < len; i++)
{
ret[len - i - 1] = (String) result.pop();
}
return ret;
}
第三步:将解析后缀表达式,返回计算的最终结果
public Object calculate(String[] endStr)
{
int len = endStr.length;
Stack calc = new Stack();
double p2;
double p1;
for (int i = 0; i < len; i++)
{
if (sign.containsKey(endStr[i]))
{
try
{
p2 = Double.parseDouble((String) calc.pop());
p1 = Double.parseDouble((String) calc.pop());
calc.push(String.valueOf(simpleCalc(p1, p2,endStr[i])));
}
catch(NumberFormatException ex)
{
ex.printStackTrace();
return "Input Error";
}
catch(Exception ex)
{
ex.printStackTrace();
return "Input Error";
}
}
else
{
calc.push(endStr[i]);
}
}
if (1 == calc.size())
{
return calc.pop();
}
else
{
return "Input Error";
}
}
public double simpleCalc(double p1, double p2, String oper)
{
switch(oper.charAt(0))
{
case '+':
return p1 + p2;
case '-':
return p1 - p2;
case '*':
return p1 * p2;
case '/':
return p1 / p2;
default:
return p1;
}
}
第四步:运算符的优先级放在了缓存中进行提取
private static HashMap sign = new HashMap();
public CalculateExp()
{
sign.put(")", "3");
sign.put("*", "2");
sign.put("/", "2");
sign.put("+", "1");
sign.put("-", "1");
sign.put("(", "0");
}
完整代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
public class CalculateExp
{
private static HashMap sign = new HashMap();
public CalculateExp()
{
sign.put(")", "3");
sign.put("*", "2");
sign.put("/", "2");
sign.put("+", "1");
sign.put("-", "1");
sign.put("(", "0");
}
public List transStr(String str)
{
List strList = new ArrayList();
String tmp = str.replaceAll("\d*", "");
String curLet = null;
int loc = 0;
int len = tmp.length();
for (int i = 0; i < len; i++)
{
curLet = tmp.substring(i, i + 1);
loc = str.indexOf(curLet);
if (!"".equals(str.substring(0, loc).trim()))
{
strList.add(str.substring(0, loc).trim());
}
strList.add(str.substring(loc, loc + 1));
str = str.substring(loc + 1);
}
if (0 < str.length())
{
strList.add(str.trim());
}
return strList;
}
public String[] midToEnd(List midList)
{
Stack embl = new Stack();
Stack result = new Stack();
Iterator it = midList.iterator();
String curStr = null;
while (it.hasNext())
{
curStr = (String) it.next();
if(sign.containsKey(curStr))
{
if (0 == embl.size() || "(".equals(curStr))
{
embl.push(curStr);
}
else
{
if(")".equals(curStr))
{
while(!"(".equals((String)embl.peek()))
{
if(0 >= embl.size())
{
return null;
}
result.push(embl.pop());
}
embl.pop();
}
else
{
int p1 = Integer.parseInt((String) sign.get(curStr));
int p2 = Integer.parseInt((String) sign.get(embl.peek()));
if (p1 > p2)
{
embl.push(curStr);
}
else
{
while (p1 <= p2 || embl.size() > 0)
{
result.push(embl.pop());
if(0 == embl.size())
{
break;
}
p2 = Integer.parseInt((String) sign.get(embl.peek()));
}
embl.push(curStr);
}
}
}
}
else
{
result.push(curStr);
}
}
while (0 < embl.size())
{
result.push(embl.pop());
}
int len = result.size();
String[] ret = new String[len];
for (int i = 0; i < len; i++)
{
ret[len - i - 1] = (String) result.pop();
}
return ret;
}
public Object calculate(String[] endStr)
{
int len = endStr.length;
Stack calc = new Stack();
double p2;
double p1;
for (int i = 0; i < len; i++)
{
if (sign.containsKey(endStr[i]))
{
try
{
p2 = Double.parseDouble((String) calc.pop());
p1 = Double.parseDouble((String) calc.pop());
calc.push(String.valueOf(simpleCalc(p1, p2,endStr[i])));
}
catch(NumberFormatException ex)
{
ex.printStackTrace();
return "Input Error";
}
catch(Exception ex)
{
ex.printStackTrace();
return "Input Error";
}
}
else
{
calc.push(endStr[i]);
}
}
if (1 == calc.size())
{
return calc.pop();
}
else
{
return "Input Error";
}
}
public double simpleCalc(double p1, double p2, String oper)
{
switch(oper.charAt(0))
{
case '+':
return p1 + p2;
case '-':
return p1 - p2;
case '*':
return p1 * p2;
case '/':
return p1 / p2;
default:
return p1;
}
}
public static void main(String[] args)
{
CalculateExp ce = new CalculateExp();
String tmp = "3+12+25*(20-20/4+10";
String ret = (String) ce.calculate(ce.midToEnd(ce
.transStr(tmp)));
double value = 0;
try
{
value = Double.parseDouble(ret);
}
catch (NumberFormatException ex)
{
System.out.print(ret);
}
System.out.print(value);
}
}
以下是其他网友的补充
代码的思路是通过正则判断计算每个最小的计算单元。以下是代码:
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CalculatorUtil {
public static BigDecimal arithmetic(String exp){
if(!exp.matches("\d+")){
String result = parseExp(exp).replaceAll("[\[\]]", "");
return new BigDecimal(result);
}else{
return new BigDecimal(exp);
}
}
private static String minExp="^((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\+\-\*\/]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))$";
private static String noParentheses="^[^\(\)]+$";
private static String priorOperatorExp="(((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\*\/]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\])))";
private static String operatorExp="(((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\+\-]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\])))";
private static String minParentheses="\([^\(\)]+\)";
private static String parseExp(String expression){
//方法进入 先替换空格,在去除运算两边的()号
expression=expression.replaceAll("\s+", "").replaceAll("^\(([^\(\)]+)\)$", "$1");
//最小表达式计算
if(expression.matches(minExp)){
String result=calculate(expression);
return Double.parseDouble(result)>=0?result:"["+result+"]";
}
//计算不带括号的四则运算
if(expression.matches(noParentheses)){
Pattern patt=Pattern.compile(priorOperatorExp);
Matcher mat=patt.matcher(expression);
if(mat.find()){
String tempMinExp=mat.group();
expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp));
}else{
patt=Pattern.compile(operatorExp);
mat=patt.matcher(expression);
if(mat.find()){
String tempMinExp=mat.group();
expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp));
}
}
return parseExp(expression);
}
//计算带括号的四则运算
Pattern patt=Pattern.compile(minParentheses);
Matcher mat=patt.matcher(expression);
if(mat.find()){
String tempMinExp=mat.group();
expression=expression.replaceFirst(minParentheses, parseExp(tempMinExp));
}
return parseExp(expression);
}
private static String calculate(String exp){
exp=exp.replaceAll("[\[\]]", "");
String number[]=exp.replaceFirst("(\d)[\+\-\*\/]", "$1,").split(",");
BigDecimal number1=new BigDecimal(number[0]);
BigDecimal number2=new BigDecimal(number[1]);
BigDecimal result=null;
String operator=exp.replaceFirst("^.*\d([\+\-\*\/]).+$", "$1");
if("+".equals(operator)){
result=number1.add(number2);
}else if("-".equals(operator)){
result=number1.subtract(number2);
}else if("*".equals(operator)){
result=number1.multiply(number2);
}else if("/".equals(operator)){
//第二个参数为精度,第三个为四色五入的模式
result=number1.divide(number2,5,BigDecimal.ROUND_CEILING);
}
return result!=null?result.toString():null;
}
}
代码原本是一个博客,原来代码没有注释而且存在BUG,我稍微修稿了一哈添加了注释。在这里做个笔记,方便以后用
另为表示对原作者的敬意,附上原始代码
public class Arithmetic {
public static void main(String args[]){
System.out.println(arithmetic("2.2+((3+4)*2-22)/2*3.2"));
}
public static double arithmetic(String exp){
String result = parseExp(exp).replaceAll("[\[\]]", "");
return Double.parseDouble(result);
}
public static String parseExp(String expression){
//String numberReg="^((?!0)\d+(\.\d+(?=0?result:"["+result+"]";
}
//计算不带括号的四则运算
String noParentheses="^[^\(\)]+$";
String priorOperatorExp="(((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\*\/]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\])))";
String operatorExp="(((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\]))[\+\-]((\d+(\.\d+)?)|(\[\-\d+(\.\d+)?\])))";
if(expression.matches(noParentheses)){
Pattern patt=Pattern.compile(priorOperatorExp);
Matcher mat=patt.matcher(expression);
if(mat.find()){
String tempMinExp=mat.group();
expression=expression.replaceFirst(priorOperatorExp, parseExp(tempMinExp));
}else{
patt=Pattern.compile(operatorExp);
mat=patt.matcher(expression);
if(mat.find()){
String tempMinExp=mat.group();
expression=expression.replaceFirst(operatorExp, parseExp(tempMinExp));
}
}
return parseExp(expression);
}
//计算带括号的四则运算
String minParentheses="\([^\(\)]+\)";
Pattern patt=Pattern.compile(minParentheses);
Matcher mat=patt.matcher(expression);
if(mat.find()){
String tempMinExp=mat.group();
expression=expression.replaceFirst(minParentheses, parseExp(tempMinExp));
}
return parseExp(expression);
}
public static String calculate(String exp){
exp=exp.replaceAll("[\[\]]", "");
String number[]=exp.replaceFirst("(\d)[\+\-\*\/]", "$1,").split(",");
BigDecimal number1=new BigDecimal(number[0]);
BigDecimal number2=new BigDecimal(number[1]);
BigDecimal result=null;
String operator=exp.replaceFirst("^.*\d([\+\-\*\/]).+$", "$1");
if("+".equals(operator)){
result=number1.add(number2);
}else if("-".equals(operator)){
result=number1.subtract(number2);
}else if("*".equals(operator)){
result=number1.multiply(number2);
}else if("/".equals(operator)){
result=number1.divide(number2);
}
return result!=null?result.toString():null;
}
}
最后给大家分享一个网友的实现方法,个人感觉也很不错
import java.util.Stack;
public class Operate {
private Stack priStack = new Stack();// 操作符栈
private Stack numStack = new Stack();;// 操作数栈
public int caculate(String str) {
// 1.判断string当中有没有非法字符
String temp;// 用来临时存放读取的字符
// 2.循环开始解析字符串,当字符串解析完,且符号栈为空时,则计算完成
StringBuffer tempNum = new StringBuffer();// 用来临时存放数字字符串(当为多位数时)
StringBuffer string = new StringBuffer().append(str);// 用来保存,提高效率
while (string.length() != 0) {
temp = string.substring(0, 1);
string.delete(0, 1);
// 判断temp,当temp为操作符时
if (!isNum(temp)) {
// 1.此时的tempNum内即为需要操作的数,取出数,压栈,并且清空tempNum
if (!"".equals(tempNum.toString())) {
// 当表达式的第一个符号为括号
int num = Integer.parseInt(tempNum.toString());
numStack.push(num);
tempNum.delete(0, tempNum.length());
}
// 用当前取得的运算符与栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;
// 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。
// 判断当前运算符与栈顶元素优先级,取出元素,进行计算(因为优先级可能小于栈顶元素,还小于第二个元素等等,需要用循环判断)
while (!compare(temp.charAt(0)) && (!priStack.empty())) {
int a = (int) numStack.pop();// 第二个运算数
int b = (int) numStack.pop();// 第一个运算数
char ope = priStack.pop();
int result = 0;// 运算结果
switch (ope) {
// 如果是加号或者减号,则
case '+':
result = b + a;
// 将操作结果放入操作数栈
numStack.push(result);
break;
case '-':
result = b - a;
// 将操作结果放入操作数栈
numStack.push(result);
break;
case '*':
result = b * a;
// 将操作结果放入操作数栈
numStack.push(result);
break;
case '/':
result = b / a;// 将操作结果放入操作数栈
numStack.push(result);
break;
}
}
// 判断当前运算符与栈顶元素优先级, 如果高,或者低于平,计算完后,将当前操作符号,放入操作符栈
if (temp.charAt(0) != '#') {
priStack.push(new Character(temp.charAt(0)));
if (temp.charAt(0) == ')') {// 当栈顶为'(',而当前元素为')'时,则是括号内以算完,去掉括号
priStack.pop();
priStack.pop();
}
}
} else
// 当为非操作符时(数字)
tempNum = tempNum.append(temp);// 将读到的这一位数接到以读出的数后(当不是个位数的时候)
}
return numStack.pop();
}
private boolean isNum(String temp) {
return temp.matches("[0-9]");
}
private boolean compare(char str) {
if (priStack.empty()) {
// 当为空时,显然 当前优先级最低,返回高
return true;
}
char last = (char) priStack.lastElement();
// 如果栈顶为'('显然,优先级最低,')'不可能为栈顶。
if (last == '(') {
return true;
}
switch (str) {
case '#':
return false;// 结束符
case '(':
// '('优先级最高,显然返回true
return true;
case ')':
// ')'优先级最低,
return false;
case '*': {
// '*/'优先级只比'+-'高
if (last == '+' || last == '-')
return true;
else
return false;
}
case '/': {
if (last == '+' || last == '-')
return true;
else
return false;
}
// '+-'为最低,一直返回false
case '+':
return false;
case '-':
return false;
}
return true;
}
public static void main(String args[]) {
Operate operate = new Operate();
int t = operate.caculate("(3+4*(4*10-10/2)#");
System.out.println(t);
}
}



