文档章节

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

_夜枫
 _夜枫
发布于 2017/03/17 11:16
字数 761
阅读 2
收藏 0

有一次计算一个数据的百分比,想把小数结果取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;

本文转载自:

_夜枫
粉丝 10
博文 506
码字总数 0
作品 0
朝阳
后端工程师
私信 提问
大数据计算服务MaxCompute 5月新功能发布一览

5月MaxCompute又发布哪些新功能,优化了哪些产品体验呢?小编带你一起看~ 【新功能】 MaxCompute提供全表扫描的设置操作 以开关的形式,通过设置允许或禁止全表扫描。true为允许,false为禁止...

晋恒
2018/06/12
0
0
阿里巴巴大数据计算平台MaxCompute(原名ODPS)全套攻略(持续更新20171127)

概况介绍 大数据计算服务(MaxCompute,原名ODPS,产品地址:https://www.aliyun.com/product/odps)是一种快速、完全托管的TB/PB级数据仓库解决方案。MaxCompute向用户提供了完善的数据导入方...

隐林
2017/05/05
0
0
MaxCompute - ODPS重装上阵 第二弹 - 新的基本数据类型与内建函数

摘要: MaxCompute(原ODPS)是阿里云自主研发的具有业界领先水平的分布式大数据处理平台, 尤其在集团内部得到广泛应用,支撑了多个BU的核心业务。 MaxCompute除了持续优化性能外,也致力于提...

阿里云云栖社区
2018/01/11
22
0
年薪500k大数据科学家:如何把阿里云maxcompute数据生活

阿里巴巴 计算的价值不只是计算,而是发现数据中隐藏的趋势。从玛雅历法到圆周比。从牛顿万有引力定律到二进制代码,甚至从创意到具体的计划。数据是无处不在的,和阿里巴巴云的maxcompute是...

daidaiweng
2018/04/19
0
0
MaxCompute常见问题(2019.04新版)

计量计费 购买开通 MaxCompute计费常见问题 现在公司有数据统计分析的需求,已经在用RDS数据库,还应该开通什么服务? 从MaxCompute上下载数据,使用华东2的ECS云主机使用内网,收取流量费用...

云花
04/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
5
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
6
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
4
0
OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
1K
11
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
40
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部