hujw 的来信 |
您好,我在使用QLExpress的时候,发现运算结果精度不符合预期结果。期盼得到您的解答。先列下具体问题:
运行表达式:a=(b-c)/(d-c)
其中:
b=new BigDecimal("0.1694915254237288"); c=new BigDecimal("0.15384615384615385"); d=new BigDecimal("1");
得到结果:a=0.01849
而我期望的结果是:a=0.01848998459167949
后者是通过BigDecimal手动运算得到的,RoundingMode=HALF_UP
疑问1:为什么QLExpress的返回结果的精度不是遵照BigDecimal的api描述的那样,精度和输入参数的精度、加减乘除方式等相关联。 疑问2:要想实现期望的结果,或者实现运算结果精度可控,有什么方法? |
回复如下:
你好,hjjw
谢谢你的咨询,我们也发现了一些源码的问题。
if(type == NumberType.NUMBER_TYPE_BIGDECIMAL) return new BigDecimal(op1.toString()).divide(new BigDecimal(op2.toString()));
应该改为:
if(type == NumberType.NUMBER_TYPE_BIGDECIMAL) return new BigDecimal(op1.toString()).divide(new BigDecimal(op2.toString()),BigDecimal.ROUND_HALF_UP);
单元测试:
@Test publicvoid testBigDecimalComputer() throws Exception { String expressString = "a=(b-c)/(d-c)"; ExpressRunner runner = new ExpressRunner(false,false); DefaultContext<String, Object> context = new DefaultContext<String, Object>(); context.put("b", new BigDecimal("0.1694915254237288")); context.put("c", new BigDecimal("0.15384615384615385")); context.put("d", new BigDecimal("1")); Object r = runner.execute(expressString, context, null, false, false); System.out.print("r="+r); } 返回结果:r=0.01848998459167949 |
接下来是两个问题:
1、因为QLExpress作为脚本语言,必须保持简洁性:a=(b-c)/(d-c),当然你可以可以按照标准java的写法使用bigdecimal
expressString = "a = (b.subtract(c)).divide(d.subtract(c), java.math.BigDecimal.ROUND_HALF_UP);"; 返回结果:r=0.01848998459167949 |
2、 参照问题1的回答
补充说明:其实QLExpress已经大量使用在后台结算系统,精度控制为RoundingMode=HALF_UP,scale=10
只要设置ExpressRunner的一个属性值即可。
/** * 是否需要高精度计算 */ privatebooleanisPrecise = false; |
@Test publicvoid testBigDecimalComputer() throws Exception { String expressString = "a=(b-c)/(d-c)"; ExpressRunner runner = new ExpressRunner(true,false); DefaultContext<String, Object> context = new DefaultContext<String, Object>(); context.put("b", new BigDecimal("0.1694915254237288")); context.put("c", new BigDecimal("0.15384615384615385")); context.put("d", new BigDecimal("1")); Object r2 = runner.execute(expressString, context, null, false, false); System.out.println("r="+r2);
} 返回结果:r=0.0184899846 |