Java高精度四则运算(无括号限制)
package cn.skyatom.common;
import java.math.BigDecimal;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 基础四则运算
*
* @author ZWK
*/
public class Arithmetic {
private static String getUUID() {
return java.util.UUID.randomUUID().toString().replaceAll("-", "");
}
public static void main(String[] args) throws Exception {
java.util.Map<String, BigDecimal> values = new java.util.HashMap<String, BigDecimal>();
BigDecimal AAF = new BigDecimal(5.5);
BigDecimal BCCC = new BigDecimal(8);
BigDecimal QQC = new BigDecimal(-8.33);
BigDecimal DCC = new BigDecimal(2);
BigDecimal EE = new BigDecimal(23);
BigDecimal BF = new BigDecimal(2.5);
BigDecimal A1 = new BigDecimal(12);
BigDecimal A2 = new BigDecimal(4);
BigDecimal A3 = new BigDecimal(5);
BigDecimal A4 = new BigDecimal(15);
values.put("AAF", AAF);
values.put("BCCC", BCCC);
values.put("QQC", QQC);
values.put("DCC", DCC);
values.put("EE", EE);
values.put("BF", BF);
values.put("A1", A1);
values.put("A2", A2);
values.put("A3", A3);
values.put("A4", A4);
//
// values.put("B1", 4F);
// values.put("B2", 15f);
// values.put("B3", 55f);
// values.put("B4", 2f);
// values.put("B5", 5f);
String str = "AAF * BCCC + QQC /DCC-EE*BF+( A1*(A2/(A3+A4)) ) ";//5.5*8 + (-8.33)/2 - 23*2.5 + (12*(4/(5+15)) )
//String str = "B1 * B2 + B3 -B4/ B5 ";//去空白
//BigDecimal v = getArithmeticValue(str, values);
System.out.println("结果为:" + getArithmeticFloatValue(str, values));
}
/**
* 执行运算,获取表达式的结果。float值
*
* @param str
* @param values
* @return
* @throws Exception
*/
public static float getArithmeticFloatValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
return getArithmeticValue(str, values).floatValue();
}
public static int getArithmeticIntValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
return getArithmeticValue(str, values).intValue();
}
public static long getArithmeticLongValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
return getArithmeticValue(str, values).longValue();
}
/**
* 替换括号
*
* @param str
* @param values
* @return 当所有替换完成,null,反之返回替换的字符串
*/
private static String replaceBrackets(String str, java.util.Map<String, BigDecimal> values) {
String v = "";
String tmp = null;//临时字符串值
Pattern patt = Pattern.compile("\\(([A-Za-z0-9\\.\\*\\+\\-/]*?)\\)", Pattern.DOTALL);
Matcher mat = patt.matcher(str);
if (mat.find()) {
tmp = mat.group(1);
}
if (tmp != null) {
String uuid = getUUID();
BigDecimal value = getBasicArithmeticValue(tmp, values);
str = str.replace("(" + tmp + ")", uuid);
values.put(uuid, value);
v = str;
v = replaceBrackets(v, values);
} else {
v = str;
}
return v;
}
/**
* 执行运算,获取表达式的结果
*
* @param str 表达式字符串
* @param values 值存储表
* @return 返回运算值
* @throws java.lang.Exception 运算格式错误时,抛出异常
*/
public static BigDecimal getArithmeticValue(String str, java.util.Map<String, BigDecimal> values) throws Exception {
str = str.replaceAll("\\s*", "");//去空白
String s = replaceBrackets(str, values);
if (s != null || !s.trim().equals("")) {
str = s;
}
return getBasicArithmeticValue(str, values);
}
/**
* 基本四则运算
*
* @param str 基础四则运算
* @param values 值存储表
* @return
*/
private static BigDecimal getBasicArithmeticValue(String str, java.util.Map<String, BigDecimal> values) {
str = multiReg(str, values);
str = divReg(str, values);
java.util.List<Boolean> signs = getPlusReduceSign(str);//获取符号
java.util.List<String> valuesign = getValueSign(str);//替换符号
BigDecimal v = getValue(valuesign, signs, values);
return v;
}
/**
* 获取结果
*
* @param valuesign 值替换符号
* @param signs 符号
* @param values 值存储表
* @return
*/
private static BigDecimal getValue(java.util.List<String> valuesign, java.util.List<Boolean> signs, java.util.Map<String, BigDecimal> values) {
BigDecimal value = values.get(valuesign.get(0));
for (int i = 0; i < signs.size(); i++) {
if (signs.get(i)) {
value = value.add(values.get(valuesign.get(i + 1)));
//value += values.get(valuesign.get(i + 1));
} else {
value = value.subtract(values.get(valuesign.get(i + 1)));
//value -= values.get(valuesign.get(i + 1));
}
}
return value;
}
/**
* 获取替换的符号
*
* @param str 待匹配的字符串
* @return 返回 替换的值符号
*/
private static java.util.List<String> getValueSign(String str) {
java.util.List<String> list = new java.util.ArrayList<String>();
Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1})", Pattern.DOTALL);
Matcher mat = patt.matcher(str);
while (mat.find()) {
if (mat.group(1).trim().equals("")) {
continue;
}
list.add(mat.group(1));
}
return list;
}
/**
* 获取加减符号
*
* @param str 待匹配的字符串
* @return 返回 符号顺序,加号为true,减号为false
*/
private static java.util.List<Boolean> getPlusReduceSign(String str) {
java.util.List<Boolean> list = new java.util.ArrayList<Boolean>();
Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1}([+|-])[a-zA-Z0-9]*{1})", Pattern.DOTALL);
Matcher mat = patt.matcher(str);
while (mat.find()) {
if (mat.group(2).trim().equals("+")) {
list.add(true);
} else {
list.add(false);
}
}
return list;
}
/**
* 乘法的正则
*
* @param str 运算表达式字符串
* @param values 值存储表
* @return 返回重构后的字符串
*/
private static String multiReg(String str, java.util.Map<String, BigDecimal> values) {
Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1}\\*[a-zA-Z0-9]*{1})", Pattern.DOTALL);
Matcher mat = patt.matcher(str);
while (mat.find()) {
str = excMultiplication(str, mat.group(1), values);
}
return str;
}
/**
* 除法的正则
*
* @param str 运算表达式字符串
* @param values 值存储表
* @return 返回重构后的字符串
*/
private static String divReg(String str, java.util.Map<String, BigDecimal> values) {
Pattern patt = Pattern.compile("([a-zA-Z0-9]*{1}\\/[a-zA-Z0-9]*{1})", Pattern.DOTALL);
Matcher mat = patt.matcher(str);
while (mat.find()) {
str = excDivsion(str, mat.group(1), values);
}
return str;
}
/**
* 计算乘法
*
* @param str 全部的运算字符串
* @param value 计算乘法的字符串
* @param map 值存储表
* @return 返回重构后的字符串
*/
private static String excMultiplication(String str, String value, java.util.Map<String, BigDecimal> map) {
String vs[] = value.split("\\*");
BigDecimal v1 = map.get(vs[0]);
BigDecimal v2 = map.get(vs[1]);
BigDecimal x = v1.multiply(v2);
map.remove(vs[0]);
map.remove(vs[1]);
String uuid = getUUID();
map.put(uuid, x);
str = str.replace(value, uuid);
return str;
}
/**
* 计算出发
*
* @param str 全部的运算字符串
* @param value 计算乘法的字符串
* @param map 值存储表
* @return 返回重构后的字符串
*/
private static String excDivsion(String str, String value, java.util.Map<String, BigDecimal> map) {
String vs[] = value.split("\\/");
BigDecimal v1 = map.get(vs[0]);
BigDecimal v2 = map.get(vs[1]);
BigDecimal x = v1.divide(v2);
map.remove(vs[0]);
map.remove(vs[1]);
String uuid = getUUID();
map.put(uuid, x);
str = str.replace(value, uuid);
return str;
}
}
最近在开发公司的绩效系统,老板又很抠门,不想购买市面上的绩效系统。。于是乎,苦逼的我又开始了苦逼的编程……