原文链接:http://zywang.iteye.com/blog/462797
在项目中有个需求,需要动态的计算一个四则运算表达式的结果,在JS中做这个非常方便,用eval表达式就搞定了,但在Java语言里就没那么容易了,上网搜了一下没有找到满意的,小弟不才,网上很多代码看不明白,唉,无奈下,自己利用Java中的正则表达式做了一个简单的包括了加减乘除及小括号的计算方法。因为时间仓促,为了赶进度,没仔细进行验证,现在贴出来,请大家拍拍砖,有什么好的解决方法,或考虑到效率问题,还请多多指教。
套话少说了,我的程序的思路是:
1、首先循环获取取最小单位的小括号表达式进行加减乘除计算,直到表达式中不包含小括号为止
2、然后对每个不含括号的表达式,在按顺序执行乘除法,直到没有乘除法表达式
3、最后计算所有的加减表达式,执行的顺序就是按顺序执行了
a)对于负数运算,首先将其负号去除,同时将相应运算单元的加减号转换,然后再进行运算
- import java.text.DecimalFormat;
- import java.text.NumberFormat;
- import java.text.SimpleDateFormat;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- /**
- * 报表工具类
- * @author ZYWANG 2009-7-28
- */
- public final class ReportUtil {
- /**
- * 格式化日期
- * @param obj 日期对象
- * @param format 格式化字符串
- * @return
- * @author ZYWANG 2009-8-26
- */
- public static String formatDate(Object obj, String format) {
- if (obj == null)
- return "";
- String s = String.valueOf(obj);
- if (format == null || "".equals(format.trim())) {
- format = "yyyy-MM-dd";
- }
- try {
- SimpleDateFormat dateFormat = new SimpleDateFormat(format);
- s = dateFormat.format(obj);
- } catch (Exception e) {
- }
- return s;
- }
- /**
- * 格式化数字
- * @param obj 数字对象
- * @param format 格式化字符串
- * @return
- * @author ZYWANG 2009-8-26
- */
- public static String formatNumber(Object obj, String format) {
- if (obj == null)
- return "";
- String s = String.valueOf(obj);
- if (format == null || "".equals(format.trim())) {
- format = "#.00";
- }
- try {
- if (obj instanceof Double || obj instanceof Float) {
- if (format.contains("%")) {
- NumberFormat numberFormat = NumberFormat.getPercentInstance();
- s = numberFormat.format(obj);
- } else {
- DecimalFormat decimalFormat = new DecimalFormat(format);
- s = decimalFormat.format(obj);
- }
- } else {
- NumberFormat numberFormat = NumberFormat.getInstance();
- s = numberFormat.format(obj);
- }
- } catch (Exception e) {
- }
- return s;
- }
- /**
- * 计算字符串四则运算表达式
- * @param string
- * @return
- * @author ZYWANG 2009-8-31
- */
- public static String computeString(String string) {
- String regexCheck = "[\\(\\)\\d\\+\\-\\*/\\.]*";// 是否是合法的表达式
- if (!Pattern.matches(regexCheck, string))
- return string;
- Matcher matcher = null;
- String temp = "";
- int index = -1;
- String regex = "\\([\\d\\.\\+\\-\\*/]+\\)";// 提取括号表达式
- string = string.replaceAll("\\s", "");// 去除空格
- try {
- Pattern pattern = Pattern.compile(regex);
- // 循环计算所有括号里的表达式
- while (pattern.matcher(string).find()) {
- matcher = pattern.matcher(string);
- while (matcher.find()) {
- temp = matcher.group();
- index = string.indexOf(temp);
- string = string.substring(0, index)
- + computeStirngNoBracket(temp)
- + string.substring(index + temp.length());
- }
- }
- // 最后计算总的表达式结果
- string = computeStirngNoBracket(string);
- } catch (NumberFormatException e) {
- return e.getMessage();
- }
- return string;
- }
- /**
- * 计算不包含括号的表达式
- * @param string
- * @return
- * @author ZYWANG 2009-8-31
- */
- private static String computeStirngNoBracket(String string) {
- string = string.replaceAll("(^\\()|(\\)$)", "");
- String regexMultiAndDivision = "[\\d\\.]+(\\*|\\/)[\\d\\.]+";
- String regexAdditionAndSubtraction = "(^\\-)?[\\d\\.]+(\\+|\\-)[\\d\\.]+";
- String temp = "";
- int index = -1;
- // 解析乘除法
- Pattern pattern = Pattern.compile(regexMultiAndDivision);
- Matcher matcher = null;
- while (pattern.matcher(string).find()) {
- matcher = pattern.matcher(string);
- if (matcher.find()) {
- temp = matcher.group();
- index = string.indexOf(temp);
- string = string.substring(0, index) + doMultiAndDivision(temp)
- + string.substring(index + temp.length());
- }
- }
- // 解析加减法
- pattern = Pattern.compile(regexAdditionAndSubtraction);
- while (pattern.matcher(string).find()) {
- matcher = pattern.matcher(string);
- if (matcher.find()) {
- temp = matcher.group();
- index = string.indexOf(temp);
- if (temp.startsWith("-")) {
- string = string.substring(0, index)
- + doNegativeOperation(temp)
- + string.substring(index + temp.length());
- } else {
- string = string.substring(0, index)
- + doAdditionAndSubtraction(temp)
- + string.substring(index + temp.length());
- }
- }
- }
- return string;
- }
- /**
- * 执行乘除法
- * @param string
- * @return
- * @author ZYWANG 2009-8-31
- */
- private static String doMultiAndDivision(String string) {
- String value = "";
- double d1 = 0;
- double d2 = 0;
- String[] temp = null;
- if (string.contains("*")) {
- temp = string.split("\\*");
- } else {
- temp = string.split("/");
- }
- if (temp.length < 2)
- return string;
- d1 = Double.valueOf(temp[0]);
- d2 = Double.valueOf(temp[1]);
- if (string.contains("*")) {
- value = String.valueOf(d1 * d2);
- } else {
- value = String.valueOf(d1 / d2);
- }
- return value;
- }
- /**
- * 执行加减法
- * @param string
- * @return
- * @author ZYWANG 2009-8-31
- */
- private static String doAdditionAndSubtraction(String string) {
- double d1 = 0;
- double d2 = 0;
- String[] temp = null;
- String value = "";
- if (string.contains("+")) {
- temp = string.split("\\+");
- } else {
- temp = string.split("\\-");
- }
- if (temp.length < 2)
- return string;
- d1 = Double.valueOf(temp[0]);
- d2 = Double.valueOf(temp[1]);
- if (string.contains("+")) {
- value = String.valueOf(d1 + d2);
- } else {
- value = String.valueOf(d1 - d2);
- }
- return value;
- }
- /**
- * 执行负数运算
- * @param string
- * @return
- * @author ZYWANG 2010-11-8
- */
- private static String doNegativeOperation(String string) {
- String temp = string.substring(1);
- if (temp.contains("+")) {
- temp = temp.replace("+", "-");
- } else {
- temp = temp.replace("-", "+");
- }
- temp = doAdditionAndSubtraction(temp);
- if (temp.startsWith("-")) {
- temp = temp.substring(1);
- } else {
- temp = "-" + temp;
- }
- return temp;
- }
- public static void main(String[] args) {
- String s = "1-7+8";
- s = computeString(s);
- System.out.println(s);
- }
- }
特别感谢lping2指出了负数运算的计算BUG。