我们在平常开发的时候,难免会遇到涉及数学公式计算的业务场景。

例如给一个公式,(1+P)*T=?,其中P和T是两个变量,当T=11、P=110时,这个公式计算的结果是多少呢?

下面给出具体实现的工具类,其实现逻辑是在Java里运行JavaScript代码。

直接运行main方法就可以得到结果了,想要换一个公式或者公式里的变量或值,就直接改下红色字体的代码即可。

import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import javax.script.*;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 使用java进行数学公式计算
 * @Author: 夏威夷8080
 * @Date: 2011/9/27 14:59
 */
@Slf4j
public class ComputeUtil {

    /**
     * js 关键词 黑名单
     */
    private static final Set<String> blacklist = Sets.newHashSet(
            // Java 全限定类名
            "java.io.File", "java.io.RandomAccessFile", "java.io.FileInputStream", "java.io.FileOutputStream",
            "java.lang.Class", "java.lang.ClassLoader", "java.lang.Runtime", "java.lang.System", "System.getProperty",
            "java.lang.Thread", "java.lang.ThreadGroup", "java.lang.reflect.AccessibleObject", "java.net.InetAddress",
            "java.net.DatagramSocket", "java.net.DatagramSocket", "java.net.Socket", "java.net.ServerSocket",
            "java.net.MulticastSocket", "java.net.MulticastSocket", "java.net.URL", "java.net.HttpURLConnection",
            "java.security.AccessControlContext", "java.lang.ProcessBuilder",
            // JavaScript 方法
            "eval","new function");

    static Compilable compilable;
    static Bindings bindings;
    static {
        ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
        compilable = (Compilable) engine;
        // Local级别的Binding
        bindings = engine.createBindings();
    }

    /**
     * 设置变量值
     * @param key 变量key
     * @param value 变量value
     */
    public static void putBindings(String key, String value){
        bindings.put(key, value);
    }

    /**
     * 清除变量值
     */
    public static void clearBindings(){
        bindings.clear();
    }

    /**
     * 计算公式
     * @param script  示例:(1+0.1 * (F/10) * T)*P
     */
    public static Double eval(String script) throws ScriptException {
        checkInsecureKeyword(script);
        CompiledScript JSFunction = compilable.compile(script);
        return Double.valueOf(String.valueOf(JSFunction.eval(bindings)));
    }

    private static void checkInsecureKeyword(String script) throws ScriptException {
        // 去除注释
        String removeComment = RegExUtils.replacePattern(script, "(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)|(?://.*)", "");
        // 多个空格替换为一个
        String finalCode = RegExUtils.replacePattern(removeComment, "\\s+", " ");
        Set<String> insecure = blacklist.stream().filter(s -> StringUtils.containsIgnoreCase(finalCode, s))
                .collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(insecure)) {
            throw new ScriptException("解析到js脚本[" + script + "]是不安全的");
        }
    }

    public static void main(String[] args) {
        bindings.put("T", 11);
        bindings.put("P", 110);
        try {
            System.out.println(eval("(1+P)*T"));
        } catch (ScriptException e) {
            e.printStackTrace();
        }
    }
}

以上就是如何在Java里进行数学公式计算的介绍,希望对你有帮助。