isPrecise

高精度计算在会计财务中非常重要,java的float、double、int、long存在很多隐式转换, 做四则运算和比较的时候其实存在非常多的安全隐患。 所以类似汇金的系统中,会有很多 BigDecimal 转换代码。

而使用QLExpress,你只要关注数学公式本身

  [plaintext]
1
订单总价 = 单价 * 数量 + 首重价格 + ( 总重量 - 首重) * 续重单价

然后设置这个属性即可,所有的中间运算过程都会保证不丢失精度

备注:但是最后的数字格式好像无法指定?

测试案例

  • 设置精度
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
/** * 测试精度设置 * @throws Exception if any */ @Test public void testPercise() throws Exception { ExpressRunner runner = new ExpressRunner(true, false); IExpressContext<String,Object> expressContext = new DefaultContext<>(); String expression ="12.3/3"; Object result = runner.execute(expression, expressContext, null, false, false); System.out.println(result); }

结果

  [plaintext]
1
4.1000000000
  • 不设置精度
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
/** * 测试非精度 * @throws Exception if any */ @Test public void testNoPercise() throws Exception { ExpressRunner runner = new ExpressRunner(false, false); IExpressContext<String,Object> expressContext = new DefaultContext<>(); String expression ="12.3/3"; Object result = runner.execute(expression, expressContext, null, false, false); System.out.println(result); }
  [plaintext]
1
4.1000000000000005

isShortCircuit

在很多业务决策系统中,往往需要对布尔条件表达式进行分析输出,普通的java运算一般会通过逻辑短路来减少性能的消耗

例如规则公式:

  [plaintext]
1
star>10000 and shoptype in('tmall','juhuasuan') and price between (100,900)

假设第一个条件 star>10000 不满足就停止运算。 但业务系统却还是希望把后面的逻辑都能够运算一遍,并且输出中间过程,保证更快更好的做出决策。

测试案例

  • ShortcutTest.java
  [java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import com.ql.util.express.DefaultContext; import com.ql.util.express.ExpressRunner; import com.ql.util.express.IExpressContext; import org.junit.Test; import java.util.ArrayList; import java.util.List; /** * <p> 短路运算符测试 </p> * * <pre> Created: 2018/6/9 下午5:27 </pre> * <pre> Project: tech-validation </pre> * * @author houbinbin * @version 1.0 * @since JDK 1.7 */ public class ShortcutTest { private ExpressRunner runner = new ExpressRunner(); private void initial() throws Exception{ runner.addOperatorWithAlias("小于","<","$1 小于 $2 不满足期望"); runner.addOperatorWithAlias("大于",">","$1 大于 $2 不满足期望"); } private boolean calculateLogicTest(String expression, IExpressContext<String, Object> expressContext, List<String> errorInfo) throws Exception { return (Boolean)runner.execute(expression, expressContext, errorInfo, true, false); } /** * 测试非短路逻辑,并且输出出错信息 * @throws Exception if any */ @Test public void testShortCircuit() throws Exception { runner.setShortCircuit(true); IExpressContext<String,Object> expressContext = new DefaultContext<>(); expressContext.put("违规天数", 100); expressContext.put("虚假交易扣分", 11); expressContext.put("VIP", false); List<String> errorInfo = new ArrayList<>(); initial(); String expression ="2 小于 1 and (违规天数 小于 90 or 虚假交易扣分 小于 12)"; boolean result = calculateLogicTest(expression, expressContext, errorInfo); showErrorInfo(result, errorInfo); } /** * 测试非短路逻辑,并且输出出错信息 * @throws Exception if any */ @Test public void testNoShortCircuit() throws Exception { runner.setShortCircuit(false); IExpressContext<String,Object> expressContext = new DefaultContext<>(); expressContext.put("违规天数", 100); expressContext.put("虚假交易扣分", 11); expressContext.put("VIP", false); List<String> errorInfo = new ArrayList<>(); initial(); String expression ="2 小于 1 and (违规天数 小于 90 or 虚假交易扣分 小于 12)"; boolean result = calculateLogicTest(expression, expressContext, errorInfo); showErrorInfo(result, errorInfo); } /** * 展现错误信息 * @param result 结果 * @param errorList 错误列表 */ private void showErrorInfo(boolean result, List<String> errorList) { if(result){ System.out.println("result is success!"); }else{ System.out.println("result is fail!"); for(String error : errorList){ System.out.println(error); } } } }
  1. testShortCircuit() 测试结果:
  [plaintext]
1
2
result is fail! 2 小于 1 不满足期望
  1. testNoShortCircuit() 测试结果:
  [plaintext]
1
2
3
result is fail! 2 小于 1 不满足期望 违规天数:100 小于 90 不满足期望