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 opts = getOptions(newExp);
List 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 getOptions(String exp) {
List opts = new ArrayList();
StringTokenizer st = new StringTokenizer(exp, "@.0123456789");
while (st.hasMoreTokens()) {
opts.add(st.nextToken().charAt(0));
}
return opts;
}
/**
* 获得一个表达式中所有的数字
* @param exp
* @return
*/
private static List getNums(String exp) {
List nums = new ArrayList();
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.替换操作(找出负号,[email protected])
* 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;
}
}