如何在Java里进行数学公式计算?

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

例如给一个公式,(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里进行数学公式计算的介绍,希望对你有帮助。

posted @   夏威夷8080  阅读(2087)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
历史上的今天:
2018-12-26 Nginx(七):keepalived实现Nginx负载均衡服务器的双机高可用
2018-12-26 Keepalived介绍以及在Linux系统下的安装与配置
2017-12-26 token登陆验证机制理解
点击右上角即可分享
微信分享提示