面試官最?lèi)?ài)問(wèn)的坑:MySQL 中 FLOAT 和 DOUBLE 你真懂嗎?
大家好呀,我是小米,今年31歲,一個(gè)依舊熱衷折騰數(shù)據(jù)庫(kù)和分享技術(shù)的大哥哥。今天要跟大家聊一個(gè)在 MySQL社招面試?yán)锾貏e常見(jiàn)的問(wèn)題:
FLOAT和DOUBLE的區(qū)別到底是什么?
別以為這是個(gè)“背誦定義”的小問(wèn)題,面試官隨便一追問(wèn),很多候選人就“翻車(chē)”了。今天我就用一個(gè)小故事,把這件事掰開(kāi)揉碎給大家講清楚,保證你下次遇到相關(guān)問(wèn)題時(shí),不僅能答,還能答得漂亮!
面試開(kāi)場(chǎng):靈魂一問(wèn)
故事要從我朋友阿輝的面試說(shuō)起。
那天他去一家互聯(lián)網(wǎng)公司面試,面試官剛寒暄了幾句,就突然拋出一句:
“阿輝,那你說(shuō)說(shuō),MySQL里FLOAT和DOUBLE有什么區(qū)別?”
阿輝心里一緊,嘴里卻條件反射地冒出:“FLOAT是單精度,DOUBLE是雙精度啊?!?/p>
面試官點(diǎn)點(diǎn)頭,追問(wèn):“那你能具體講講,它們?cè)?nbsp;MySQL8.x 中各自存儲(chǔ)空間、精度表現(xiàn)、使用場(chǎng)景上有什么差別嗎?如果我要存貨幣數(shù)據(jù),你覺(jué)得該用哪個(gè)?”
阿輝:“呃……這個(gè)……我記得FLOAT是4字節(jié),DOUBLE是8字節(jié)吧,具體精度差多少我忘了,存貨幣的話(huà)……是不是用DOUBLE?”
面試官笑了笑,沒(méi)說(shuō)話(huà)。阿輝的心涼了一半。
知識(shí)點(diǎn)拆解:FLOAT和DOUBLE的區(qū)別
我當(dāng)時(shí)聽(tīng)完阿輝復(fù)盤(pán),差點(diǎn)沒(méi)笑噴。其實(shí)他沒(méi)答錯(cuò),但答得太淺了。
面試官真正想聽(tīng)的,是以下幾個(gè)層次:
1. 存儲(chǔ)空間
- FLOAT:?jiǎn)尉雀↑c(diǎn)數(shù),占 4字節(jié)(32位)。
- DOUBLE:雙精度浮點(diǎn)數(shù),占 8字節(jié)(64位)。
MySQL8.x 官方文檔明確寫(xiě)了,DOUBLE 是 FLOAT 的精度擴(kuò)展版。
2. 精度
- FLOAT:大約能保證 7位十進(jìn)制有效數(shù)字。
- DOUBLE:大約能保證 15~16位十進(jìn)制有效數(shù)字。
換句話(huà)說(shuō),F(xiàn)LOAT能表示的數(shù)不如DOUBLE精確,尤其在做科學(xué)計(jì)算、金融數(shù)據(jù)統(tǒng)計(jì)時(shí),誤差可能被放大。
3. 存儲(chǔ)方式
這兩個(gè)字段都是遵循 IEEE 754 標(biāo)準(zhǔn) 的浮點(diǎn)數(shù)表示方式。
內(nèi)部是“符號(hào)位 + 指數(shù)位 + 尾數(shù)位”的結(jié)構(gòu),而不是直接存小數(shù)。
這也是為什么很多人用FLOAT/DOUBLE存貨幣會(huì)翻車(chē)的原因:
比如 0.1 + 0.2 在浮點(diǎn)數(shù)表示里,結(jié)果并不是等于 0.3,而是 0.30000000000000004。
4. 范圍
- FLOAT:±1.17549e-38 到 ±3.40282e38
- DOUBLE:±2.22507e-308 到 ±1.79769e308
DOUBLE 的表示范圍更大,適合高精度科學(xué)計(jì)算。
5. 顯示精度
MySQL5.x 曾經(jīng)支持寫(xiě)法:FLOAT(M,D) 或 DOUBLE(M,D)
- M = 總位數(shù)
- D = 小數(shù)位數(shù)
但在 MySQL 8.0.17 之后,這種寫(xiě)法被棄用了,因?yàn)樗菀鬃屓苏`解精度,官方推薦用 DECIMAL 來(lái)控制小數(shù)點(diǎn)位數(shù)。
案例演示:誤差現(xiàn)場(chǎng)
有些人聽(tīng)到這里可能還沒(méi)直觀(guān)感受,我來(lái)給大家舉個(gè)例子。
假設(shè)有一個(gè)商品價(jià)格,19.99 元,你用FLOAT存,結(jié)果可能會(huì)發(fā)生什么?
圖片
結(jié)果有可能顯示成:19.989999771118
而如果你用DOUBLE:
圖片
結(jié)果可能顯示成:19.990000000000002
是不是傻眼了?你以為的 19.99,數(shù)據(jù)庫(kù)卻“偷偷改造”了一下。
這就是浮點(diǎn)數(shù)的誤差問(wèn)題!
面試官的陷阱:貨幣到底用哪個(gè)?
我敢打賭,很多面試官問(wèn)FLOAT和DOUBLE,其實(shí)最后都會(huì)拋出終極問(wèn)題:
“如果要存貨幣數(shù)據(jù),用FLOAT還是DOUBLE?”
正確答案其實(shí)是:都不用!
貨幣數(shù)據(jù)一定要用 DECIMAL(M,D),因?yàn)镈ECIMAL是定點(diǎn)數(shù),用字符串存儲(chǔ)并計(jì)算,能保證十進(jìn)制精度,不會(huì)出現(xiàn)浮點(diǎn)誤差。
比如:
圖片
這樣存儲(chǔ) 19.99,才會(huì)保證無(wú)誤差。
所以答題套路就是:
- 先答FLOAT和DOUBLE的區(qū)別。
- 再補(bǔ)充說(shuō)明浮點(diǎn)數(shù)存貨幣會(huì)出問(wèn)題。
- 最后推薦用DECIMAL,這樣面試官一定覺(jué)得你“考慮全面”。
常見(jiàn)坑點(diǎn)總結(jié)
為了防止大家踩坑,我把FLOAT和DOUBLE的典型問(wèn)題總結(jié)下:
- 精度不足:FLOAT常常丟精度,DOUBLE雖然更好,但也不是絕對(duì)精確。
- 計(jì)算誤差:浮點(diǎn)數(shù)運(yùn)算存在四舍五入、進(jìn)位問(wèn)題。
- 顯示差異:存進(jìn)去的數(shù)和查詢(xún)出來(lái)的數(shù)可能“肉眼不一樣”。
- 不適合貨幣:財(cái)務(wù)類(lèi)應(yīng)用必須用DECIMAL。
- 兼容性問(wèn)題:某些語(yǔ)言(如Java、Python)取MySQL浮點(diǎn)數(shù)時(shí),會(huì)遇到二進(jìn)制轉(zhuǎn)十進(jìn)制的小數(shù)問(wèn)題,要特別小心。
我和阿輝的復(fù)盤(pán)
面試結(jié)束后,阿輝愁眉苦臉跑來(lái)找我:“小米,你快救救我,我感覺(jué)FLOAT和DOUBLE把我坑慘了!”
我笑著拍拍他:“兄弟,你其實(shí)沒(méi)答錯(cuò),只是答得太淺。下次你這樣答:
- FLOAT是4字節(jié)單精度,DOUBLE是8字節(jié)雙精度;
- FLOAT大約7位有效數(shù)字,DOUBLE能到15-16位;
- 存儲(chǔ)方式遵循IEEE 754,存在誤差問(wèn)題;
- 范圍DOUBLE更大;
- 存貨幣數(shù)據(jù)應(yīng)該用DECIMAL。
保證面試官立刻滿(mǎn)意地點(diǎn)頭,還可能反問(wèn)一句:‘喲,你還挺懂行的嘛?!?/p>
阿輝聽(tīng)完,恍然大悟:“原來(lái)這才是面試標(biāo)準(zhǔn)答案??!”
擴(kuò)展思考
其實(shí),F(xiàn)LOAT和DOUBLE的問(wèn)題背后,考察的是候選人對(duì)計(jì)算機(jī)存儲(chǔ)和精度問(wèn)題的理解。
很多人光背概念,一追問(wèn)就露怯。面試官真正想確認(rèn)的是:
- 你能不能把知識(shí)點(diǎn)說(shuō)到位?
- 你能不能結(jié)合實(shí)際場(chǎng)景給出合適的方案?
- 你有沒(méi)有意識(shí)到工程上的坑?
說(shuō)白了,能從“定義層面”上升到“應(yīng)用層面”,才是真正的技術(shù)深度。
總結(jié)
好了,今天的故事就講到這里,我們來(lái)收個(gè)尾:
1、FLOAT vs DOUBLE
- FLOAT:?jiǎn)尉龋?字節(jié),7位有效數(shù)字。
- DOUBLE:雙精度,8字節(jié),15-16位有效數(shù)字。
2、區(qū)別
- 存儲(chǔ)空間不同。
- 精度范圍不同。
- 都會(huì)有誤差,不適合存貨幣。
3、最佳實(shí)踐
- 科學(xué)計(jì)算:用DOUBLE。
- 財(cái)務(wù)數(shù)據(jù):用DECIMAL。
- 需要存儲(chǔ)大范圍但允許誤差:FLOAT也可。
所以,下次面試官再問(wèn)你FLOAT和DOUBLE的區(qū)別時(shí),別只回答“單精度 vs 雙精度”,一定要補(bǔ)充 存儲(chǔ)空間、精度、范圍、應(yīng)用場(chǎng)景、坑點(diǎn),再順帶提一句“貨幣要用DECIMAL”,妥妥加分!
































