【MaxCompute学习】隐式转化的问题
来源:互联网 发布:nginx flask windows 编辑:程序博客网 时间:2024/06/05 15:29
有一次计算一个数据的百分比,想把小数结果取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.66select round(0.0067 ,4)*100 from dual; --0.67select round(0.0068 ,4)*100 from dual; --0.6799999999999999select 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.66select 0.0067*100 from dual;--0.67select 0.0068*100 from dual;--0.6799999999999999select 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.0068select cast(100 as double) from dual;--100.0select 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学习】隐式转化的问题
- MaxCompute计算长尾问题
- 编码转化的问题
- 类型转化的问题
- 背包问题的转化
- objectmapper的转化问题
- 从未停止进化的MaxCompute
- 从未停止进化的MaxCompute
- 关于MaxCompute的基本了解
- MaxCompute上你从未体验过的数据分析和机器学习过程
- Odps(MaxCompute)使用时一些问题
- (odps)maxcompute 日志操作学习
- scala的隐式转化
- 关于String转化的问题
- 一个图像转化的问题
- SVM 之 问题的转化
- usb_modeswitch 自动转化的问题
- Javascript学习【类型转化问题总汇】
- 当python爬虫遇到10060错误
- java集合
- ClassLoader读取文件的路径
- ARM_Linux和虚拟机linux通过socket通信
- 深入理解Java:注解(Annotation)--注解处理器
- 【MaxCompute学习】隐式转化的问题
- Error:(2) Error: "app_name" is not translated in "en" (English), "zh" (Chine
- CSS常用背景图片定位方法
- java compiler level does not match the version of the installed java project facet
- Mybatis接口式编程
- 华为oj初级 分解因数
- MFC界面库BCGControlBar v25.1新版亮点四:网格控件等
- 前端们?你们还是没有方向?资源?内容?你要的都在这,好好花三五年沉淀下吧!
- 机器学习中防止过拟合的处理方法