`
express_wind
  • 浏览: 29576 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics