MySQL float猜想

問題描述

使用JPA映射一個float類型到數據庫:

clipboard.png

然後存儲129364.57,發現存儲的結果是129365

clipboard.png

從上週就開始研究這個問題,查閱了各種資料,網上許多人都說是因爲MySQL默認是保留六位有效數字,自己測試了一下也確實是這樣。但是查詢MYSQL官方文檔,並沒有找到依據。

MySQL官方文檔:Float - MySQL

如果你看到了這篇文章,歡迎評論發表意見,讓我們互相學習、進步。

結論

寫的非常好的一篇文章,MySQL存儲的各種嘗試:MySQL數字類型int與tinyint、float與decimal如何選擇

clipboard.png

JPA映射的Float默認的長度與小數點都是0

clipboard.png

這是測試的結果:float默認能精確到6位有效數字!

原理猜想

這是MySQL官方文檔對floatdouble的描述:

官方文檔並沒有說MySQL是如何存儲浮點數的,所以如果沒有去讀過其源代碼,所有的博客都只是猜想。

clipboard.png

IEEE 754

目前大多數人認爲MySQL內部是採用IEEE 754進行存儲的,IEEE 754 - 維基百科

IEEE二進制浮點數算術標準(IEEE 754)是20世紀80年代以來最廣泛使用的浮點數運算標準,爲許多CPU與浮點運算器所採用。

32位的單精度浮點數爲例:

clipboard.png

與日常所說的科學計數法類似。

因爲底數是有效數字,所以第一位肯定是1,所以這個1不進行存儲,所以雖然是23位的底數,但是實際的底數位數其實是24位,含有一個隱含的1

雙精度與此類似,一個符號位,指數位爲11,尾數爲52位,合計64位。

假設

假設是用MySQL是用IEEE 754標準存儲的浮點數。

用單精度存儲129364.57,其二進制爲11111100101010100.1001000111101011100001010001111011

clipboard.png

正數:符號位爲0

指數位爲:00010000(十進制中的16)。

去掉第一個1,保留23位,底數爲:11111001010101001001000

所以最後的結果是11111100101010100.1001000,轉換爲十進制爲:129364.5625

clipboard.png

但是實際的MySQL存儲後的結果爲129365,所以猜想要麼MySQL就是不是按IEEE 754存儲的,要麼就是按這個存儲的但是內部爲了數據庫的性能等或其他的優化對數據進行了處理。

這裏我這裏更傾向於第二種,畢竟IEEE 754是一種國際標準,沒有理由不遵守。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章