hive源码之decimal乘法精度和标度计算

大家好,我是老六。 

在数据开发中,对于需要精确保留的字段我们一般都会用decimal类型来进行存储,老六通过源码研究了decimal乘法精度和标度计算原理,我们一起来看下decimal乘法精度和标度到底计算的吧。

一、使用

Hive中的decimal类型与Java的Big Decimal格式相同。它用于表示不变的任意精度。语法和示例如:decimal(prec,scale)

这里我们对decimal类型做两点说明:
1)decimal(9,8)代表最多9位数字,后8位是小数。此时也就是说,小数点前最多有1位数字,如果超过一位则会变成null。
2)decimal(最大精度为38位,不指定小数位数的话,将会四舍五入到整数位,所以在定义的时候一定要定义精度,如(10,2))。

二、案例

1、正常案例

SQL:select  cast(100.1 as decimal(4,1))*cast(1.1 as decimal(2,1));

结果:

执行计划: explain SELECT  cast(100.1 as decimal(4,1))*cast(1.1 as decimal(2,1));

STAGE DEPENDENCIES:
  Stage-0 is a root stage

STAGE PLANS:
  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        TableScan
          alias: _dummy_table
          Row Limit Per Split: 1
          Statistics: Num rows: 1 Data size: 1 Basic stats: COMPLETE Column stats: COMPLETE
          Select Operator
            expressions: 110.11 (type: decimal(7,2))
            outputColumnNames: _col0
            Statistics: Num rows: 1 Data size: 112 Basic stats: COMPLETE Column stats: COMPLETE
            ListSink

三、源码

1.2.1版本的GenericUDFOPMultiply 类的关键代码

public class GenericUDFOPMultiply extends GenericUDFBaseNumeric {

.....

  @Override

  protected DecimalTypeInfo deriveResultDecimalTypeInfo(int prec1, int scale1, int prec2, int scale2) {

    int scale = Math.min(HiveDecimal.MAX_SCALE, scale1 + scale2 );

    int prec = Math.min(HiveDecimal.MAX_PRECISION, prec1 + prec2 + 1);

    return TypeInfoFactory.getDecimalTypeInfo(prec, scale);

  }

}

其中 HiveDecimal.MAX_SCALE 和 HiveDecimal.MAX_PRECISION 的值都是38。

    从上面的关键代码中可以看到,在1.2.1中,没有重新校准精度的地方,而是使用简单粗暴的方式,各自计算precision和scale的精度,这就会导致在真实数据很大的时候,计算出来的值的精度达不到预期,也就是会不准确。

四、总结

纸上得来终觉浅,绝知此事要躬行。对于工作学习过程中遇到的问题希望大家能够亲自实践,找到答案。


欢迎关注微信公众号

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值