java中实现四则运算代码

网友投稿 291 2023-07-29


java中实现四则运算代码

最近上网查了一下,竟然没有找到用java编写的四则运算的代码,就小写了一下.如有问题请大家反馈.

1.说明

代码只是实现了简单的四则运算,支持+,-,*,/,(,) 只能计算出正确的表达式的值,没有对非法表达式进行校验.

2.实现方法

第一步:将输入的字符串转换为List,主要是用来将String转换为原子:数值/运算符/括号

public List transStr(String str)

{

List strList = new ArrayList();

/* 获取提出数据的符号串 */

String tmp = str.replaceAll("\\d*", "");

/* 记录当前的运算符 */

String curLet = null;

/* 记录tmp字符串中第一个运算符的位置 */

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;

}

第三步:将解析后缀表达式,返回计算的最终结果

/**

* 解析后缀表达式,返回对应的运算结果

* @param String[] endStr 转换后的后缀表达式

* @return Object 返回运算结果 如果表达式有误直接打印"Input Error"

*/

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";

}

}

/**

* 实现底层的运算函数

* @param double p1 数字1

* @param double p1 数字2

* @param String oper 运算符 +-/*

*/

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;

/**

* Java实现计算表达式

* 只实现有加减乘除以及括号的运算

* 例如: 3+12+25*(20-20/4)+10

* @author GuoBo 2009-3-16

* @version 1.0

*/

public class CalculateExp

{

private static HashMap sign = new HashMap();

/* 将运算符的优先级放入到缓存处理 */

public CalculateExp()

{

sign.put(")", "3");

sign.put("*", "2");

sign.put("/", "2");

sign.put("+http://", "1");

sign.put("-", "1");

sign.put("(", "0");

}

/**

* @param String 输入的表达式

* @return List 解析后的字符串元素

* 对输入的字符串进行解析

* 转换为需要处理的数据

* 例如:3+12+25*(20-20/4)+10

* 转换后的结果为:

* List 元素为 ret = {3,+,12,+,25,*,(,20,-,20,-,20,/,4,),+,10}

*/

public List transStr(String str)

{

List strList = new ArrayList();

/* 获取提出数据的符号串 */

String tmp = str.replaceAll("\\d*", "");

/* 记录当前的运算符 */

String curLet = null;

/* 记录tmp字符http://串中第一个运算符的位置 */

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;

}

/**

* 将表达式从中缀表达式转换为后缀表达式(波兰式)

* @Param List 解析后的表达式的列表

* @return String[] 转换后的表达式字符串数组

*/

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;

}

/**

* 解析后缀表达式,返回对应的运算结果

* @param String[] endStr 转换后的后缀表达式

* @return Object 返回运算结果 如果表达式有误直接打印"Input Error"

*/

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";

}

}

/**

* 实现底层的运算函数

* @param double p1 数字1

* @param double p1 数字2

* @param String oper 运算符 +-/*

*/

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;

/**

* 计算器工具类

* @author shuqi

* @date 2015-7-23

* @version since 1.0

*/

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="\\([^\\(\\)]+\\)";

/**

* 解析计算四则运算表达式,例:2+((3+4)*2-22)/2*3

* @param expression

* @return

*/

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);

}

/**

* 计算最小单位四则运算表达式(两个数字)

* @param exp

* @return

*/

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,我稍微修稿了一哈添加了注释。在这里做个笔记,方便以后用

/**

* 四则运算表达式计算

* @author penli

*

*/

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);

}

/**

* 解析计算四则运算表达式,例:2+((3+4)*2-22)/2*3

* @param expression

* @return

*/

public static String parseExp(String expression){

//String numberReg="^((?!0)\\d+(\\.\\d+(?<!0))?)|(0\\.\\d+(?<!0))$";

expression=expression.replaceAll("\\s+", "").replaceAll("^\\((.+)\\)$", "$1");

String checkExp="\\d";

String minExp="^((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))[\\+\\-\\*\\/]((\\d+(\\.\\d+)?)|(\\[\\-\\d+(\\.\\d+)?\\]))$";

//最小表达式计算

if(expression.matches(minExp)){

String result=calculate(expression);

return Double.parseDouble(result)>=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);

}

/**

* 计算最小单位四则运算表达式(两个数字)

* @param exp

* @return

*/

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;

/**

* 利用栈,进行四则运算的类

* 用两个栈来实现算符优先,一个栈用来保存需要计算的数据numStack,一个用来保存计算优先符priStack

*

* 基本算法实现思路为:用当前取得的运算符与priStack栈顶运算符比较优先级:若高于,则因为会先运算,放入栈顶;

* 若等于,因为出现在后面,所以会后计算,所以栈顶元素出栈,取出操作数运算;

* 若小于,则同理,取出栈顶元素运算,将结果入操作数栈。各个优先级'(' > '*' = '/' > '+' = '-' > ')'

*

*/

public class Operate {

private Stack priStack = new Stack();// 操作符栈

private Stack numStack = new Stack();;// 操作数栈

/**

* 传入需要解析的字符串,返回计算结果(此处因为时间问题,省略合法性验证)

* @param str 需要进行技术的表达式

* @return 计算结果

*/

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();

}

/**

* 判断传入的字符是不是0-9的数字

*

* @param str

* 传入的字符串

* @return

*/

private boolean isNum(String temp) {

return temp.matches("[0-9]");

}

/**

* 比较当前操作符与栈顶元素操作符优先级,如果比栈顶元素优先级高,则返回true,否则返回false

*

* @param str 需要进行比较的字符

* @return 比较结果 true代表比栈顶元素优先级高,false代表比栈顶元素优先级低

*/

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);

}

}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:简介alert()与console.log()的不同
下一篇:ajax如何实现页面局部跳转与结果返回
相关文章

 发表评论

暂时没有评论,来抢沙发吧~