【MaxCompute学习】隐式转化的问题
有一次計算一個數據的百分比,想把小數結果取2位,并拼接一個百分號展示在結果報表中。用到的sql如下
很奇怪局部數據并沒有保留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.6799999999999999double浮點數運算的時候會有丟失精度的問題,這個是所有的浮點數運算的通病,我們可以再java下驗證一下
public?class?TestDouble?{public?static?void?main(String?args[]){Double?a=0.0068;Double?b=100.0;System.out.println(a*b);//0.6799999999999999Double?c=0.0067;Double?d=100.0;System.out.println(c*d);//0.67BigDecimal?e=?new?BigDecimal(0.0068);BigDecimal?f=new?BigDecimal(100.0);System.out.println(e.multiply(f));//0.679999999999999962113639284666533058043569326400756835937500BigDecimal?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;
原文鏈接:http://click.aliyun.com/m/14019/
轉載于:https://blog.51cto.com/11778640/1906468
總結
以上是生活随笔為你收集整理的【MaxCompute学习】隐式转化的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 另类玩法:通过 DNS 进行文件传输
- 下一篇: 我会铭记这一天:2016年10月25日