【MaxCompute学习】隐式转化的问题

简介: MaxCompute使用小技巧

有一次计算一个数据的百分比,想把小数结果取2位,并拼接一个百分号展示在结果报表中。用到的sql如下

select concat(round(10230/1497409,4)*100,'%') from  dual;

很奇怪局部数据并没有保留2位小数,比如上面的数据返回的是67.99999999999999

我计算了下上面的结果大概得到的数据为0.0068

select concat(round(0.0066 ,4)*100,'%') from  dual;--0.66%
select concat(round(0.0067 ,4)*100,'%') from  dual;--0.67%
select concat(round(0.0068 ,4)*100,'%') from  dual;--0.6799999999999999%
select concat(round(0.0069 ,4)*100,'%') from  dual;--0.69%

由于计算值采用了concat函数,concat的多个参数为string类型,如果输入为bigint,decimal,double,datetime类型会隐式转化为string类型,并且返回的为string类型

也就是说有两种情况

1.round函数返回的数字cast为string后就丢失了精度。 2.round函数返回的数字就丢失了精度。

select round(0.0066 ,4)*100 from dual; --0.66
select round(0.0067 ,4)*100 from dual; --0.67
select round(0.0068 ,4)*100 from dual; --0.6799999999999999
select round(0.0069 ,4)*100 from dual; --0.69

上面的结果说明是round函数返回的数字就丢失了精度。

round函数是用来计算指定到小数点位数的四舍五入的值的,如果其第一个参数为double类型,那么函数计算的结果就是double类型,如果其第一个参数为Decimal类型,那么函数计算的结果就是decimal类型的,如果其第一个参数为string类型或者bigint类型,那么就会隐式转化为double类型。

单独计算round的返回值如下,说明double类型的round返回值为double

select round(0.0068 ,4) from dual; --0.0068

再计算乘法的结果,double和bigint相计算的时候也是会发生隐式转化的

select 0.0066*100 from dual;--0.66
select 0.0067*100 from dual;--0.67
select 0.0068*100 from dual;--0.6799999999999999
select 0.0069*100 from dual;--0.69

对于操作符号的运算,string,bigint和double都可以参与算术运算,string类型会转成double类型计算 当bigint和bigint进行除法运算的时候结果会返回double类型,当bigint和double共同计算的时候,big今天会转成doule类型,并且返回结果为double类型,

那么100变成了double类型,这时候问题就有点眉目了

select cast(0.0068 as double) from dual;--0.0068
select cast(100 as double) from dual;--100.0
select 0.0068*100.0 from dual;--0.6799999999999999

double浮点数运算的时候会有丢失精度的问题,这个是所有的浮点数运算的通病,我们可以再java下验证一下

public class TestDouble {
    public static void main(String args[]){
        Double a=0.0068;
        Double b=100.0;

        System.out.println(a*b);//0.6799999999999999

        Double c=0.0067;
        Double d=100.0;

        System.out.println(c*d);//0.67

        BigDecimal e= new BigDecimal(0.0068);
        BigDecimal f=new BigDecimal(100.0);

        System.out.println(e.multiply(f));//0.679999999999999962113639284666533058043569326400756835937500

        BigDecimal g= new BigDecimal(Double.toString(0.0068));
        BigDecimal h=new BigDecimal(Double.toString(100.0));

        System.out.println(g.multiply(h));//0.68000
    }
}

当然这个问题的最终解决方案很简单,不过以后再计算对精度要求比较高的数据的时候建议还是设计成decimal类型

select round(10230*100/1497409,4) from  dual;


文章转载自wangming

欢迎加入“数加·MaxCompute购买咨询”钉钉群(群号: 11782920)进行咨询,群二维码如下:

96e17df884ab556dc002c912fa736ef6558cbb51
相关实践学习
基于MaxCompute的热门话题分析
Apsara Clouder大数据专项技能认证配套课程:基于MaxCompute的热门话题分析
目录
相关文章
|
SQL NoSQL Java
Redis学习---大数据技术之Redis(NoSQL简介、Redis简介、Redis安装、五大数据类型、相关配置、持久化)
Redis学习---大数据技术之Redis(NoSQL简介、Redis简介、Redis安装、五大数据类型、相关配置、持久化)
|
分布式计算 大数据 Java
大数据-87 Spark 集群 案例学习 Spark Scala 案例 手写计算圆周率、计算共同好友
大数据-87 Spark 集群 案例学习 Spark Scala 案例 手写计算圆周率、计算共同好友
337 5
|
分布式计算 关系型数据库 MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
大数据-88 Spark 集群 案例学习 Spark Scala 案例 SuperWordCount 计算结果数据写入MySQL
260 3
|
数据采集 搜索推荐 算法
Java 大视界 -- Java 大数据在智能教育学习社区用户互动分析与社区活跃度提升中的应用(274)
本文系统阐述 Java 大数据技术在智能教育学习社区中的深度应用,涵盖数据采集架构、核心分析算法、活跃度提升策略及前沿技术探索,为教育数字化转型提供完整技术解决方案。
|
存储 分布式计算 算法
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
大数据-106 Spark Graph X 计算学习 案例:1图的基本计算、2连通图算法、3寻找相同的用户
503 0
|
数据采集 数据可视化 大数据
大数据体系知识学习(三):数据清洗_箱线图的概念以及代码实现
这篇文章介绍了如何使用Python中的matplotlib和numpy库来创建箱线图,以检测和处理数据集中的异常值。
601 1
大数据体系知识学习(三):数据清洗_箱线图的概念以及代码实现
|
分布式计算 大数据 Hadoop
大数据学习
【10月更文挑战第2天】大数据学习
671 16
|
存储 SQL 分布式计算
大数据学习
【10月更文挑战第15天】
468 1
|
存储 Prometheus NoSQL
大数据-44 Redis 慢查询日志 监视器 慢查询测试学习
大数据-44 Redis 慢查询日志 监视器 慢查询测试学习
331 3
|
分布式计算 大数据 Linux
大数据体系知识学习(二):WordCount案例实现及错误总结
这篇文章介绍了如何使用PySpark进行WordCount操作,包括环境配置、代码实现、运行结果和遇到的错误。作者在运行过程中遇到了Py4JJavaError和JAVA_HOME未设置的问题,并通过导入findspark初始化和设置环境变量解决了这些问题。文章还讨论了groupByKey和reduceByKey的区别。
414 1

热门文章

最新文章

相关产品

  • 云原生大数据计算服务 MaxCompute