irpas技术客

hive中计算精度 double和decimal 的精度差异示例_其未远_hive中double支持的最大精度

网络投稿 3691

我们先看一下这几个sql在hive中的返回值: hive中整数默认给int类型带有小数位的给double类型可以通过cast(num as decimal(n,m)) 指定数字类型int类型是最弱的类型,它和其他两个操作后会被转换double是最强的类型,和其他两个类型操作时会全部转换成dluble类型使用double运算时可能会导致精度丢失,如对精度要求较高,建议全都换成decimal类型之后再做操作。 select cast('0.00407' as decimal(18,6))*2500 --10.175 select cast('0.00407' as decimal(18,6))*cast(2500 as decimal(18,2)) --10.175 select cast('0.00407' as decimal(18,6))*cast(2500 as double) -- 10.174999999999999 explain select 200; --返回值类型:int explain select 200.00; --返回值类型:double explain select 200*200.00 --返回值类型:double explain select 200*cast(200.00 as decimal(18,2)) --返回值类型:decimal explain select 200.00*cast(200.00 as decimal(18,2)) --返回值类型:double 两个declimal计算不会造成精度丢失double和decimal计算可能造成精度缺失 1、hive将字符串默认转换成double类型进行计算 执行一下代码: --'0.00407' 是double,2500 是int类,结果是double类 explain select '0.00407'*2500 -->10.1749999999 执行计划 - 可以看到,hive将字符串 ‘0.0407’ 转换成 double类型,最终输出值是: 10.1749999999 2、将字符转换成decimal后再计算 执行下面代码: --2500 是int类型,和decimal类行计算后为 decimal explain select cast('0.00407' as decimal(18,6))*2500 --> 10.175 执行计划 - 将字符串 ‘0.0407’ 转换成 decimal类型之后再计算,结果为: 10.175 decimal 运算先后导致的精度丢失 hive中即使数值都是decimal,也有可能造成精度缺失 。因为下一步的计算是以上一个计算结果为基础的,所以任何一部出现无法准确表达的数值时都可能造成精度缺失 select 100/12*6 --50.0 select cast(100 as decimal(18,2))/12*6 --49.999998 select cast(100 as decimal(18,2))/cast(12 as decimal(18,2))*cast(6 as decimal(18,2)) --49.999998 select cast(100 as decimal(18,2))*6/12 --50 100 /12 *6 这算式在逻辑上与 100 * 6/12 和 100/2 等价,但是100/12不能尽除,导致中间出现中间值:8.33333333333333 导致最终结果丢失精度,结果为:49.999998对于decimal类型来说,计算时应尽量让乘法在除法前计算 总结 虽然两个代码的返回值是:10.1749999999 、 10.175 看上去差异很小,但如果将数值通过round函数精确到两位数,则分别返回 10.17 和 10.18 。在金融领域查一分钱的话还是需要注意的,很可能造成资金不对等。hive中double和decimal两个类型计算会返回double,有可能造成精度缺失。应该把两个计算值都转换成decimal类型。对于decimal类型来说,计算时应尽量让乘法在除法前计算,减少中间值无法精确表示的情况。

高精度计算时,尽量多保留两位小数,并吧数据转换成decimal类型后再做计算,以免精度丢失


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #hive中计算精度 #double和decimal #select #004072500