1.round函數(shù)的四舍五入
1.1問題解決
今天在導(dǎo)出報表時,發(fā)現(xiàn)有個字段金額的值為 501.42990000000003元榔至,很明顯這是出現(xiàn)了精度丟失的問題了,于是我準備使用round函數(shù)進行四舍五入欺劳,取2位小數(shù)來使用唧取,但是卻發(fā)現(xiàn)round函數(shù)小坑不斷。
首先我們假定現(xiàn)在需要處理的值為 12345678.445
如果此時這個值是數(shù)值類型杰标,那么使用round函數(shù)得到的結(jié)果是
看起來我們已經(jīng)達到了目標是嗎兵怯?
但是由于我這個數(shù)值是varchar類型,實際的結(jié)果卻是
我們需要的四舍五入并沒有達成腔剂。
那么就是字符不能簡單的使用round函數(shù)進行四舍五入媒区,那么我們需要把字符轉(zhuǎn)成數(shù)值進行操作了。
第一次轉(zhuǎn)換
按照網(wǎng)上的經(jīng)驗,我們在字符串后面加了個0袜漩,結(jié)果卻依然沒有錯誤绪爸。
第二次轉(zhuǎn)換
這個我們使用cast函數(shù)
。宙攻。奠货。。這次結(jié)果完全不對座掘,為什么嗯递惋?
原因在于使用這個函數(shù)方法時,注意AS DECIMAL函數(shù)的2個參數(shù),第一個9代表的是數(shù)值有效位,第二個2代表小數(shù)的有效位帅霜,按照(9绿贞,2)來處理的話,我們能得到的最大數(shù)值是9-2=7位的整數(shù)部分,和2位的小數(shù)部分,這樣最大的數(shù)值也只能是圖中 的9999999.99了,所以我們在使用這個函數(shù)時邓馒,要根據(jù)業(yè)務(wù)情況給出合適的數(shù)值位數(shù),最后使用了20位長度蛾坯,成功達成目標
1.2 問題分析
目標達成了光酣,我們再回看下在這個問題處理中,我們都碰到了什么問題偿衰?
1:為什么會出現(xiàn)最開始501.42990000000003元這種需要轉(zhuǎn)換的數(shù)據(jù)挂疆?
通過查看sql發(fā)現(xiàn),這個金額是由單價*數(shù)量得到的下翎,而我在表結(jié)構(gòu)中缤言,單價才用了Bigdecmal類型,而數(shù)值使用了varchaer類型视事,結(jié)果就是
這就提醒我們胆萧,如果我們在建表時,嚴格按照業(yè)務(wù)數(shù)據(jù)類型建表俐东,類似這個數(shù)量采用數(shù)值類型存儲跌穗,就不出現(xiàn)的這種隱藏的BUG了。
2: 為什么在處理round在處理字符串類型的數(shù)字時虏辫,會得到不到我們想要的結(jié)果蚌吸。
首先,round函數(shù)在處理時砌庄,會根據(jù)傳入的參數(shù)羹唠,有不同的處理方法奕枢,
參數(shù)會分成兩類,一種是精確值佩微,整數(shù)類型int和bigdecimal缝彬,另外一種都可以算成近似值數(shù)字,具體分類可以查看官方文檔哺眯。
mysql中關(guān)于精確值和近似值的定義
分清楚參數(shù)類型后谷浅,如果是精確值,那么系統(tǒng)的操作就是我們通常理解的四舍五入了奶卓。
mysql文檔中關(guān)于舍入的說明
如果是近似值的話按照以下四舍六入五成雙規(guī)則處理
-
被修約的數(shù)字小于5時一疯,該數(shù)字舍去;
4小于5寝杖,被舍去 被修約的數(shù)字大于5時违施,則進位;
-
被修約的數(shù)字等于5時,要看5前面的數(shù)字留潦,若是奇數(shù)則進位只盹,若是偶數(shù)則將5舍掉,
5前面是奇數(shù)兔院,進一位
若5的后面還有不為“0”的任何數(shù),則此時無論5的前面是奇數(shù)還是偶數(shù)坊萝,均應(yīng)進位孵稽。
此處參考了以下網(wǎng)友資料
https://q.cnblogs.com/q/94377/