java根据公式计算结果

发布于 2019-12-30  1.26k 次阅读


<!-- 依赖 -->
<!-- https://mvnrepository.com/artifact/org.mvel/mvel2 -->
		<dependency>
			<groupId>org.mvel</groupId>
			<artifactId>mvel2</artifactId>
			<version>2.4.5.Final</version>
		</dependency>
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import com.jeecg.pay.util.SimpleStringUtils;

import org.mvel2.CompileException;
import org.mvel2.MVEL;
import org.mvel2.PropertyAccessException;
import org.springframework.util.NumberUtils;

/**
 * 工具类
 */
public class CalculateUtils {

    /**
     * 根据传入的公式和参数进行计算
     *
     * @param formula
     * @param variables
     * @return
     */
    public static <T> BigDecimal calculate(String formula, Map<String, T> variables) {
        if (SimpleStringUtils.isBlank(formula)) {
            throw new CalculateException("MVEL formula can't be null! formula : " + formula); // 公式不能为空
        }
        if (variables == null || variables.size() == 0) {
            throw new CalculateException("MVEL variables can't be null! variables : " + String.valueOf(variables)); // 参数不能为空
        }

        try {
            // 将公式中的变量全部转化为BigDecimal类型
            variables.entrySet().stream().filter(e -> e != null && e.getKey() != null && e.getValue() != null)
                    .map(CalculateUtils::convert).collect(Collectors.toMap(Entry::getKey, Entry::getValue));

        } catch (NumberFormatException e) {
            throw new CalculateException(
                    "MVEL can't convert to BigDecimal, please check the variables : " + String.valueOf(variables) + "!",
                    e);
        } catch (Exception e) {
            throw e;
        }
        BigDecimal result = null;
        try {
            result = (BigDecimal) MVEL.eval(formula, variables);
        } catch (PropertyAccessException pae) {
            throw new CalculateException(
                    "MVEL please check the formula :" + formula + " & variables : " + String.valueOf(variables) + "!",
                    pae);
        } catch (CompileException ce) {
            throw new CalculateException("MVEL calculate error! ", ce);
        } catch (Exception e) {
            throw e;
        }
        // 四舍五入 保留小数点后面2位数
        return result.setScale(2, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * 将参数转化为Bigdecimal类型
     *
     * @param entry
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> Entry<String, T> convert(Entry<String, T> entry) {
        if (entry != null) {
            BigDecimal value = null;
            if (entry.getValue() instanceof BigDecimal) {
                value = (BigDecimal) entry.getValue();
            } else {
                value = getBigDecimal(entry.getValue());
            }
            entry.setValue((T) value);
        }
        return entry;
    }

    /**
     * Object转BigDecimal类型
     * @param value 要转的object类型
     * @return 转成的BigDecimal类型数据
     */
    public static BigDecimal getBigDecimal(Object value) {
        BigDecimal ret = null;
        if (value != null) {
            if (value instanceof BigDecimal) {
                ret = (BigDecimal) value;
            } else if (value instanceof String) {
                ret = new BigDecimal((String) value);
            } else if (value instanceof BigInteger) {
                ret = new BigDecimal((BigInteger) value);
            } else if (value instanceof Number) {
                ret = new BigDecimal(((Number) value).doubleValue());
            } else {
                throw new ClassCastException("Not possible to coerce [" + value + "] from class " + value.getClass() + " into a BigDecimal.");
            }
        }
        return ret;
    }

}
/**
 * 异常类
 */
public class CalculateException extends RuntimeException {

    /**
     * Constructs a {@code CalculateException} with no detail message.
     */
    public CalculateException() {
        super();
    }

    /**
     * Constructs a {@code CalculateException} with the specified detail
     * message.
     *
     * @param message
     *            the detail message.
     */
    public CalculateException(String message) {
        super(message);
    }

    /**
     * Constructs a {@code CalculateException} with the specified detail
     * message & cause
     *
     * @param message
     * @param cause
     */
    public CalculateException(String message, Throwable cause) {
        super(message, cause);
    }

}
/**
 * 字符串工具
 */
public class SimpleStringUtils {

    /**
     * 判断字符串不为空
     *
     * @param str
     * @return
     */
    public static boolean isNotBlank(String str) {
        return !isBlank(str);
    }

    /**
     * 判断字符串为空
     *
     * @param str
     * @return
     */
    public static boolean isBlank(String str) {
        if (str == null || "".equals(str.trim())) {
            return true;
        }
        return false;
    }

    /**
     *  去首尾空格
     *
     * @param s
     * @return
     */
    public static <T> String trim(T s) {
        if (s instanceof String) {
            return s == null ? null : ((String) s).trim();
        } else {
            return s == null ? null : String.valueOf(s).trim();
        }
    }

    /**
     * 下划线命名转驼峰式
     *
     * @param str
     * @return
     */
    public static String toCamel(String str) {
        if (SimpleStringUtils.isBlank(str)) {
            return str;
        }
        StringBuffer buffer = new StringBuffer();
        str = str.toLowerCase().trim();
        char[] charArray = str.toCharArray();
        if (charArray != null) {
            for (int i = 0; i < charArray.length; i++) {
                if ('_' == charArray[i]) {
                    i = i + 1;
                    buffer.append(Character.toUpperCase(charArray[i]));
                } else {
                    buffer.append(charArray[i]);
                }
            }
        }
        return buffer.toString();
    }

    /**
     * 驼峰转下划线
     *
     * @param str
     * @return
     */
    public static String toUnderline(String str) {
        if (SimpleStringUtils.isBlank(str)) {
            return str;
        }
        StringBuffer buffer = new StringBuffer();
        str = str.trim();
        char[] charArray = str.toCharArray();
        if (charArray != null) {
            for (int i = 0; i < charArray.length; i++) {
                if (Character.isUpperCase(charArray[i])) {
                    buffer.append("_");
                    buffer.append(Character.toLowerCase(charArray[i]));
                } else {
                    buffer.append(charArray[i]);
                }
            }
        }
        return buffer.toString();
    }
}
	public static void main(String[] args) throws Exception{

		String formula = "AA * Bb - ( C-D) + G / H";

		Map<String, Object> variables = new HashMap<>();
		variables.put("AA", "20.12");
		variables.put("Bb", 12.22);
		variables.put("C", 30.12);
		variables.put("D", 20.33);
//		variables.put("E", new BigDecimal("20"));
//		variables.put("F", "3");
		variables.put("G", "20.24");
		variables.put("H", "2.11");

		BigDecimal result = CalculateUtils.calculate(formula, variables);
		System.out.println(result);

//		Assert.assertTrue(new BigDecimal("10000.0").compareTo(result) == 0);
	}

此文章转载:

https://blog.csdn.net/valsong/article/details/77874711

https://blog.csdn.net/kisscatforever/article/details/80331991


公交车司机终于在众人的指责中将座位让给了老太太