MySQL中ROUND函數(shù)進(jìn)行四舍五入操作陷阱分析
本文實(shí)例講述了MySQL中ROUND函數(shù)進(jìn)行四舍五入操作陷阱。分享給大家供大家參考,具體如下:
在MySQL中, ROUND
函數(shù)用于對查詢結(jié)果進(jìn)行四舍五入,不過最近使用ROUND
函數(shù)四舍五入時(shí)意外發(fā)現(xiàn)并沒有預(yù)期的那樣,本文將這一問題記錄下來,以免大家跟我一樣犯同樣的錯(cuò)誤。
問題描述
假如我們有如下一個(gè)數(shù)據(jù)表 test ,建表語句如下
CREATE TABLE test ( id int(11) NOT NULL AUTO_INCREMENT, field1 bigint(10) DEFAULT NULL, field2 decimal(10,0) DEFAULT NULL, field3 int(10) DEFAULT NULL, field4 float(15,4) DEFAULT NULL, field5 float(15,4) DEFAULT NULL, field6 float(15,4) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我們創(chuàng)建了一個(gè)名為 test 的表,出了 id 字段之外還包含了多個(gè)字段,擁有這不同的數(shù)據(jù)類型。我們向這個(gè)表中插入一條數(shù)據(jù)
INSERT INTO test (field1, field2, field3, field4, field5, field6) VALUE (100, 100, 100, 1.005, 3.5, 2.5);
插入之后表中的數(shù)據(jù)是這樣的
mysql> select * from test; +----+--------+--------+--------+--------+--------+--------+ | id | field1 | field2 | field3 | field4 | field5 | field6 | +----+--------+--------+--------+--------+--------+--------+ | 1 | 100 | 100 | 100 | 1.0050 | 3.5000 | 2.5000 | +----+--------+--------+--------+--------+--------+--------+ 1 rowin set (0.00 sec)
如果現(xiàn)在我們執(zhí)行下面這個(gè)SQL,你覺得結(jié)果會是什么樣的呢?
SELECT round(field1 * field4), round(field2 * field4), round(field3 * field4), round(field1 * 1.005), round(field2 * 1.005), round(field3 * 1.005), round(field5), round(field6) FROM test;
最初一直以為這樣的結(jié)果肯定是都是 101 ,因?yàn)樯厦孢@六個(gè)取值結(jié)果都是對 100 * 1.005 進(jìn)行四舍五入,結(jié)果肯定都是 101 才對,而后面兩個(gè)肯定是 4 和 3 才對,但是最終的結(jié)果卻是與設(shè)想的大相徑庭
*************************** 1. row *************************** round(field1 * field4): 100 round(field2 * field4): 100 round(field3 * field4): 100 round(field1 * 1.005): 101 round(field2 * 1.005): 101 round(field3 * 1.005): 101 round(field5): 4 round(field6): 2 1 rowin set (0.00 sec)
為什么會這樣?
同樣是100*1.005,為什么從數(shù)據(jù)庫中的字段相乘得到的結(jié)果和直接字段與小數(shù)相乘得到的不一樣呢?
對這個(gè)問題百思不得其解,各種百度谷歌無果。。。沒辦法,還得靠自己,這個(gè)時(shí)候最有用的就是官網(wǎng)文檔了,于是查詢了mysql官方文檔中關(guān)于ROUND函數(shù)的部分,其中包含下面兩條規(guī)則
- For exact-value numbers, ROUND() uses the “round half up” rule(對于精確的數(shù)值, ROUND 函數(shù)使用四舍五入)
- For approximate-value numbers, the result depends on the C library. On many systems, this means that ROUND() uses the “round to nearest even” rule: A value with any fractional part is rounded to the nearest even integer. (對于近似值,則依賴于底層的C函數(shù)庫,在很多系統(tǒng)中
ROUND
函數(shù)會使用“取最近的偶數(shù)”的規(guī)則)
通過這兩條規(guī)則,我們可以看出,由于我們在使用兩個(gè)字段相乘的時(shí)候,最終的結(jié)果是按照 float 類型處理的,而在計(jì)算機(jī)中 float 類型不是精確的數(shù),因此處理結(jié)果會按照第二條來,而直接整數(shù)字段與1.005這樣的小數(shù)運(yùn)算的結(jié)果是因?yàn)閮蓚€(gè)參與運(yùn)算的值都是精確數(shù),因此按照第一條規(guī)則計(jì)算。從 field5 和 field6 執(zhí)行 ROUND
函數(shù)的結(jié)果可以明確的看確實(shí)是轉(zhuǎn)換為了最近的偶數(shù)。
總結(jié)
從這個(gè)例子中可以看到,在MySQL中使用ROUND
還是要非常需要注意的,特別是當(dāng)參與計(jì)算的字段中包含浮點(diǎn)數(shù)的時(shí)候,這個(gè)時(shí)候計(jì)算結(jié)果是不準(zhǔn)確的。
更多關(guān)于MySQL相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《MySQL查詢技巧大全》、《MySQL事務(wù)操作技巧匯總》、《MySQL存儲過程技巧大全》、《MySQL數(shù)據(jù)庫鎖相關(guān)技巧匯總》及《MySQL常用函數(shù)大匯總》
希望本文所述對大家MySQL數(shù)據(jù)庫計(jì)有所幫助。
相關(guān)文章
MySQL數(shù)據(jù)庫中sql表設(shè)計(jì)的注意事項(xiàng)
實(shí)際開發(fā)中一個(gè)項(xiàng)目通常需要很多張表才能完成,這篇文章主要給大家介紹了關(guān)于MySQL數(shù)據(jù)庫中sql表設(shè)計(jì)的注意事項(xiàng),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-05-05MySQL參數(shù)優(yōu)化信息參考(my.cnf參數(shù)優(yōu)化)
下面針對一些參數(shù)進(jìn)行說明,當(dāng)然還有其它的設(shè)置可以起作用,取決于你的負(fù)載或硬件:在慢內(nèi)存和快磁盤、高并發(fā)和寫密集型負(fù)載情況下,你將需要特殊的調(diào)整2024-07-07Mysql查詢數(shù)據(jù)庫連接狀態(tài)以及連接信息詳解
這篇文章主要給大家介紹了關(guān)于Mysql查詢數(shù)據(jù)庫連接狀態(tài)以及連接信息的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2023-04-04利用phpmyadmin設(shè)置mysql的權(quán)限方法
這篇文章主要介紹了如何利用phpmyadmin設(shè)置mysql的權(quán)限方法,需要的朋友可以參考下2018-03-03Mysql在Windows系統(tǒng)快速安裝部署方法(綠色免安裝版)
這篇文章主要介紹了Mysql在Windows系統(tǒng)快速安裝部署方法(綠色免安裝版),需要的朋友可以參考下2017-06-06MySQL千萬數(shù)據(jù)量深分頁優(yōu)化流程(拒絕線上故障)
這篇文章主要為大家介紹了MySQL千萬數(shù)據(jù)量深分頁優(yōu)化拒絕線上故障,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05