- package com.fire.utils;
- import java.text.DecimalFormat;
- import java.text.NumberFormat;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.StringTokenizer;
- /**
- * 工具类
- *
- * @author FireAnt
- *
- */
- public class Tools {
- public static int i = 0;
- /**
- * 计算一个合法的表达式的值
- * @param exp
- * @return
- */
- public static String cal(String exp) {
- // 特殊表达式的处理方式
- if (exp.length() == 0) {
- return "";
- } else if (exp.length() == 1) {
- if (exp.equals(".")) {
- return "0";
- } else {
- return "";
- }
- } else if (exp.matches(".*÷0.*")) { // 0作为除数
- return "∞";
- } else if (exp.matches(".*[+-/×÷]")) {
- exp = exp.substring(0, exp.length() - 1);
- if (exp.equals(".")) {
- return "0";
- }
- }
- // 如果表达式中有括号则递归计算
- if (exp.contains("(")) {
- // 找出最后一个左括号
- int left = exp.lastIndexOf("(");
- // 找出第一个右括号
- int right = exp.indexOf(")");
- // 获取第一个子表达式
- String subExp = exp.substring(left + 1, right);
- // 计算子表达式的结果
- String res = cal(subExp);
- // 用计算出来的结果替换子表达式
- exp = exp.substring(0, left) + res + exp.substring(right + 1);
- // 递归计算新的表达式
- exp = cal(exp);
- }
- // 格式化表达式
- String newExp = formatExp(exp);
- List<Character> opts = getOptions(newExp);
- List<Double> nums = getNums(newExp);
- // 先处理乘除
- for (int i = 0; i < opts.size(); i++) {
- char opt = opts.get(i);
- if (opt == '÷' || opt == '×') {
- opts.remove(i);
- double d1 = nums.remove(i);
- double d2 = nums.remove(i);
- if (opt == '÷') {
- d1 = d1 / d2;
- } else {
- d1 = d1 * d2;
- }
- nums.add(i, d1);
- i--;
- }
- }
- while (!opts.isEmpty()) {
- char opt = opts.remove(0);
- double d1 = nums.remove(0);
- double d2 = nums.remove(0);
- if (opt == '+') {
- d1 = d1 + d2;
- } else {
- d1 = d1 - d2;
- }
- nums.add(0, d1);
- }
- return formatNum(nums.get(0));
- }
- /**
- * 获得一个表达式中所有的运算符
- * @param exp
- * @return
- */
- private static List<Character> getOptions(String exp) {
- List<Character> opts = new ArrayList<Character>();
- StringTokenizer st = new StringTokenizer(exp, "@.0123456789");
- while (st.hasMoreTokens()) {
- opts.add(st.nextToken().charAt(0));
- }
- return opts;
- }
- /**
- * 获得一个表达式中所有的数字
- * @param exp
- * @return
- */
- private static List<Double> getNums(String exp) {
- List<Double> nums = new ArrayList<Double>();
- StringTokenizer st = new StringTokenizer(exp, "+-×÷");
- while (st.hasMoreTokens()) {
- String num = st.nextToken();
- if (num.contains("@")) {
- num = "-" + num.substring(1);
- }
- nums.add(Double.parseDouble(num));
- }
- return nums;
- }
- /**
- * 格式一个浮点数
- * @param num
- * @return
- */
- public static String formatNum(double num) {
- DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
- df.applyLocalizedPattern("#0.##########");
- if (num > 1000000000) {
- df.applyPattern("#0.#######E0");
- }
- return df.format(num);
- }
- /**
- * 格式化表达式
- * 1.替换操作(找出负号,并将其替换成@符号)
- * 2.避免非法表达式的出现
- */
- private static String formatExp(String exp) {
- // 如果表达式是以运算符结束的,则将最后一位运算符去除
- if (exp.matches(".*[+-/×÷]")) {
- exp = exp.substring(0, exp.length() - 1);
- }
- String res = exp;
- if (exp.charAt(0) == '-') {
- res = "@" + res.substring(1);
- }
- for (int i = 1; i < res.length(); i++) {
- if (res.charAt(i) == '-' && (res.charAt(i - 1) == '÷' || res.charAt(i - 1) == '×')) {
- res = res.substring(0, i) + "@" + res.substring(i + 1);
- }
- }
- return res;
- }
- /**
- * 检查表达式是否有括号,并且检查是否符合
- * @param exp
- * @return
- */
- public static boolean checkExp(String exp) {
- boolean res = true;
- int index = exp.indexOf("(");
- if (index != -1) {
- int leftN = 0;
- for (int i = index; i < exp.length(); i++) {
- if (exp.charAt(i) == '(') {
- leftN++;
- }
- else if (exp.charAt(i) == ')') {
- leftN--;
- if (leftN == -1) {
- res = false;
- break;
- }
- }
- }
- if (leftN > 0) {
- res = false;
- }
- }
- return res;
- }
- }
- //该片段来自于http://www.codesnippet.cn/detail/2301201511605.html
来源: http://www.codesnippet.cn/detail/2301201511605.html