Java处理数学公式得出结果
Java处理数学公式得出结果
杨润康Bla 发表于2年前
Java处理数学公式得出结果
  • 发表于 2年前
  • 阅读 26
  • 收藏 1
  • 点赞 2
  • 评论 0

【腾讯云】新注册用户域名抢购1元起>>>   

支持含有字母的复杂表达式、不含字母的纯数学表达式

先上测试程序,后面有源码:
1.纯数字的算式测试

    public static void main(String[] args) throws Exception {
        String express = "(100-5+45)*88.8/(5/94+584)";
        Double result = MathFormulaUtil.getNumberResult(express);
        System.out.println(result); //结果:21.28573250031876
    }

2.带有字母的公式测试

public static void main(String[] args) throws Exception {
        String express = "(((x+y)/(z+x)*q)+100-99)*565";
        //输入参数
        double[] param = new double[]{45,89,200,45,66};
        Double result =MathFormulaUtil.getExpressionResult(express, param);
        System.out.println(result); //结果:20960.346938775518
    }

下面是程序源码:

/* 说明: 首先需要导入2个jar包: expression4jCFG.jar expression4j.jar 上面2个jar包依赖于日志记录,所以还需要导入下面几个日志包. slf4j-api-1.5.11.jar log4j-1.2.17.jar slf4j-log4j12-1.5.11.jar 上面的jar包在文章的末尾有下载 */
package com.usi.jrwl.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import fr.expression4j.basic.MathematicalElement;
import fr.expression4j.core.Expression;
import fr.expression4j.core.Parameters;
import fr.expression4j.factory.ExpressionFactory;
import fr.expression4j.factory.NumberFactory;
/** * 输入数学公式即可计算结果 * @author 杨润康 */
public class MathFormulaUtil {

    /** * 根据用户输入的数学算式返回表达式对象 * @param expressionString 用户输入 数学算式 * @param params 按照变量的位置为变量输入[对应]的值 * @return 计算结果 * @throws Exception * * note:在英文输入法的状态下输入 */
    public static Double getExpressionResult(String expressionString,double...params) throws Exception{
        // ( ) + - * / 0-9是数学中的表达式 其余的部分是变量 x y z 等等
        //注意消除空格
        //第一步 去除空格
        expressionString.trim().replace(" ","");
        //第二步 获取每个字符串的每个字符 后面主要做过滤
        String[] expressArgs = expressionString.split("");
        //创建过滤器 过滤出来除 ( ) + - * / 数字 0-9 之外的其余字符
        List<String> filters = Arrays.asList("(",")","+","-","*","/","0","1","2","3","4","5","6","7","8","9");
        //过滤出结果 即过滤出用户输入的变量
        List<String> vars = new ArrayList<String>();//存放过滤结果 
        int count = -1;
        for(String arg : expressArgs){
            count++; //计数 从0
            if(!filters.contains(arg)){ //字符不在工具类中
                if(!arg.equals("")){  //空格不能加入其中 
                    //处理重复变量的问题
                    if(vars.contains(arg)){ //如果已经过滤的结果中包含了当前循环的编号 追加随机数 避免让key值不一样,这样不会发生替换
                        String argRandom = arg+getRandom(); // f(x,x12) 中变了,还得让 = (x+x2)中对应的变量也变 处理方法 count
                        //替换原表达式,即等号后面的部分
                        String oldChar = expressionString.substring(count-1); //等号 替换循环位置后面的部分 后面原字符
                        //不能直接替换 这样会都替换掉 我只是替换循环位置后面的部分
                        String repStrLater = oldChar.replace(oldChar, argRandom);
                        //更新等号后面的表达式 截掉旧的替换新的
                        expressionString = expressionString.substring(0,count-1)+repStrLater+expressionString.substring(count);
                        vars.add(argRandom);
                        count = count +32; //补充随机字符串的剩余长度,,以保证坐标准确
                    }else{ //不包含 正常添加
                        vars.add(arg);
                    }
                }
            }
        }
        //构建表达式 "f(x,y,z,..)="
        StringBuilder expressionHead = new StringBuilder("f(");
        for(String v : vars){
            expressionHead.append(v+",");
        }
        //将最后一个 , 去掉
        expressionHead.setLength(expressionHead.length()-1);
        expressionHead.append(")=");
        //完整的表达式
        String expressionAll = expressionHead + expressionString;
        //创建表达式对象
        Expression expression = ExpressionFactory.createExpression(expressionAll);

        //为参数赋值放入List中 顺序不能乱
        List<MathematicalElement> mes = new ArrayList<MathematicalElement>();

        //输入的参数 params
        //构建数学元素
        for (int i = 0; i < params.length; i++) {
            mes.add(NumberFactory.createReal(params[i]));
        }

        //从表达式工厂创建一个空的参数
        Parameters parameters = ExpressionFactory.createParameters();
        //对应参数赋值
        for(int i=0;i<vars.size();i++){
            //这边是键值的形式存储的,所以第二个,传过来的第二个x的值,或由于键是一样的,而替换掉第一次键对应的值,及2--->4,键还是那个键 x
            //解决方法 键的区分 : 过滤用户表达式中的变量时加一个方法 即 与已经过滤出来结果再此比较,如果在出现一样的键,重新命名采用追加随机数的方式 
            parameters.addParameter(vars.get(i),mes.get(i));//vars 变量 mes 变量对应的值 
        }
        //返回结果
        return expression.evaluate(parameters).getRealValue();
    }

    /** * 支持纯数字计算 * @param expressionString 用户输入 数学算式 * @return 计算结果 * @throws Exception 异常 */
    public static Double getNumberResult(String expressionString) throws Exception{
        Expression expression = ExpressionFactory.createExpression("f()="+expressionString);
        return expression.evaluate(null).getRealValue();
    }

    /** * 生成随机数 */
    public  static String getRandom(){
        String s = UUID.randomUUID().toString();
        return s.substring(0, 8) + s.substring(9, 13) + s.substring(14, 18) + s.substring(19, 23) + s.substring(24);
    }
}

jar包下载地址:http://sourceforge.net/projects/expression4j/

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 14
博文 76
码字总数 0
×
杨润康Bla
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: