QLExpress脚本语言技术讲解(9)-------高精度计算

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的返回结果的精度不是遵照BigDecimalapi描述的那样,精度和输入参数的精度、加减乘除方式等相关联。

疑问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_UPscale=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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值