在Java中,计算会出现失精度的情况:
一般情况下可以使用BigDecimal进行精确计算,但是如果需要进行复杂公式的计算,就比较麻烦了,我这里通过引用js脚本引擎来实现java的精确计算。
下面这个工具类提供了两个精确计算方法:
1.analyticalMathematicalFormula(String formula)上传的字符串公式中必须对应具体数值,才能精确计算出结果。
package com.xj;
/**
* @program:Java_ssw
* @description:
* @author:尚龙龙
* @create:2021-06-28-16:49
**/
public class Demo {
public static void main(String[] args) {
double num = (double)AccurateCalculationTools.analyticalMathematicalFormula("(1 + 1) * 8 / (86000) - 1");
System.out.println("结果:" + num);
}
}
结果:-0.9998139534883721
2.analyticalMathematicalFormula(String rule, Map<String, Object> maps)推荐使用,当计算公式的数值为动态时使用
package com.xj;
/**
* @program:Java_ssw
* @description:
* @author:尚龙龙
* @create:2021-06-28-16:49
**/
public class Demo {
public static void main(String[] args) {
Map<String,Object> map = new HashMap<String, Object>();
map.put("A",1);
map.put("B",1);
map.put("C",8);
map.put("D",86000);
map.put("E",1);
double num = (double)AccurateCalculationTools.analyticalMathematicalFormula("(A + B) * C / (D) - E",map);
System.out.println("结果:" + num);
}
}
结果:-0.9998139534883721
工具类
package com.xj.utils;
import javax.script.*;
import java.util.*;
import java.util.Map;
/**
* @program:Java_trs
* @description:精确计算工具类
* @author:尚龙龙
* @create:2021-05-27-09:19
**/
public class AccurateCalculationTools {
public static Object analyticalMathematicalFormula(String formula) {
//替换中英文括号
formula = formula.replace("(", "(");
formula = formula.replace(")", ")");
Object result = formula;
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
try {
result = engine.eval(formula);//
} catch (ScriptException e) {
return result;
}
return result;
}
public static Object analyticalMathematicalFormula(String rule, Map<String, Object> maps) {
rule = rule.replace(" ", "");
//规则
// String rule = "score1/score2";
//计算参数
// String[] params = {"score1", "score2"};
//实体类
// Map<String, Object> map = new HashMap();
// map.put("score1", 1.0);
// map.put("score2", 86400.0);
// Contents contents = new HeaderFooter.Contents();
// contents.setScore1(1);
// contents.setScore2(2);
// contents.setScore3(3);
//对象转json
// JSONObject jsonObj = JSONObject.fromObject(contents);
//
//ScriptEngineManager manager = new ScriptEngineManager();
//通过文件扩展名获取脚本引擎
ScriptEngine engine = new ScriptEngineManager().getEngineByName("js");
//将参数和实体类中的值 封装到hash中
Map<String, Object> paramValues = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : maps.entrySet()) {
String param = entry.getKey();
double value = (double)entry.getValue();
paramValues.put(param, value);
}
// for (String param : map.entrySet()) {
// paramValues.put(param, JsonUtils.getParamValue(jsonObj, param));
// }
//将hash转成集合 便于循环遍历
Iterator<String> keys = paramValues.keySet().iterator();
//将key和value 封装到脚本引擎中
while (keys.hasNext()) {
String key = keys.next();
if (engine.get(key) == null) {
engine.put(key, paramValues.get(key));
}
}
//脚本引擎通过rule的计算公式 计算结果
Object calcValue = null;
try {
calcValue = engine.eval(rule);
} catch (ScriptException e) {
}
return calcValue;
}
}