3 回答

TA貢獻1831條經驗 獲得超4個贊
這是我懷疑時發現的。
mysql> create table numbers (a decimal(10,2), b float);
mysql> insert into numbers values (100, 100);
mysql> select @a := (a/3), @b := (b/3), @a * 3, @b * 3 from numbers \G
*************************** 1. row ***************************
@a := (a/3): 33.333333333
@b := (b/3): 33.333333333333
@a + @a + @a: 99.999999999000000000000000000000
@b + @b + @b: 100
十進制確實完成了對這種情況應該做的事情,它截斷了其余部分,從而失去了1/3部分。
因此,對于總和,小數點更好,但對于除法,浮點數更好,當然還有一些點。我的意思是,使用DECIMAL不會以任何方式為您提供“失敗證明算術”。
希望這可以幫助。

TA貢獻1813條經驗 獲得超2個贊
大多數環境中的“浮點”是二進制浮點類型。它可以準確地存儲base-2值(到某個點),但不能準確存儲許多base-10(十進制)值。浮子最適合科學計算。它們不適合大多數面向商業的數學運算,不合適地使用花車會讓你感到困惑。許多十進制值無法在base-2中精確表示。0.1
例如,你不能看到像這樣的奇怪結果1.0 - 0.1 = 0.8999999
。
小數存儲基數為10的數字。對于大多數商業數學而言,十進制是一個很好的類型(但任何內置的“貨幣”類型更適合于財務計算),其中值的范圍超過整數類型提供的值,并且需要小數值。顧名思義,小數是為基數10設計的 - 它們可以準確地存儲十進制值(再次,到某一點)。

TA貢獻1911條經驗 獲得超7個贊
MySQL最近改變了他們存儲DECIMAL類型的方式。在過去,他們為每個數字存儲字符(或nybbles),包括數字的ASCII(或nybble)表示 - vs - 二進制補碼整數或其衍生物。
DECIMAL的當前存儲格式是一系列1,2,3或4字節整數,其位被連接以創建帶有隱含小數點的二進制補碼數,由您定義,并在您聲明時存儲在DB模式中列,并指定它的DECIMAL大小和小數點位置。
舉例來說,如果你采用32位int,你可以存儲0 - 4,294,967,295之間的任何數字。這只能可靠地覆蓋999,999,999,所以如果你扔出2位并使用(1 << 30 -1)你就什么也不放棄。僅使用4個字節覆蓋所有9位數字比使用4個ASCII字符或8個nybble數字覆蓋32位中的4位數字更有效。(一個nybble是4位,允許值0-15,超過0-9所需的值,但你不能通過轉到3位來消除這種浪費,因為它只涵蓋0-7的值)
MySQL在線文檔中使用的示例使用DECIMAL(18,9)作為示例。這比隱含小數點前面的9位數字和9位數字要短,如上所述,需要以下存儲空間。
18個8位字符:144位
作為18個4位nybbles:72位
作為2個32位整數:64位
目前DECIMAL最多支持65位數字,如DECIMAL(M,D),其中M允許的最大值為65,D允許的最大值為30。
為了不一次要求9位數的塊,小于32位的整數用于使用1,2和3字節整數來添加數字。出于某種原因,無視邏輯,使用了簽名而不是無符號的int,并且這樣做,1位被拋出,從而產生以下存儲能力。對于1,2和4字節的整數,丟失的位無關緊要,但對于3字節的int來說,這是一場災難,因為整個數字由于丟失了這一位而丟失。
使用7位int:0 - 99
使用15位int:0 - 9,999
使用23位int:0 - 999,999(0 - 9,999,999,帶有24位int)
1,2,3和4字節整數連接在一起形成“位池”DECIMAL用于將數字精確地表示為二進制補碼整數。小數點未存儲,暗示。
這意味著數據庫引擎不需要ASCII到int轉換就可以將“數字”轉換為CPU識別為數字的內容。沒有舍入,沒有轉換錯誤,它是CPU可以操作的實數。
對這個任意大整數的計算必須在軟件中完成,因為這種數字沒有硬件支持,但這些庫非常陳舊且經過高度優化,已在50年前編寫,以支持IBM 370 Fortran任意精度浮點數據。它們仍然比使用CPU整數硬件完成的固定大小整數代數慢,或者在FPU上進行浮點計算。
就存儲效率而言,因為float的指數附加到每個浮點數,隱含地指定小數點的位置,所以它是大量冗余的,因此對DB工作來說效率低。在數據庫中,您已經知道小數點的位置在前面,并且表中具有DECIMAL列值的每一行只需要查看該小數點的放置位置的唯一規范,存儲在模式中作為DECIMAL(M,D)的參數作為M和D值的含義。
這里發現的關于哪種格式用于各種應用程序的許多評論是正確的,所以我不會強調這一點。我花時間在這里寫這篇文章,因為無論是誰維護鏈接的MySQL在線文檔都不理解上述任何內容,并且經過多次令人沮喪的嘗試向他們解釋它后,我放棄了。很好地表明他們對所寫內容的理解程度有多差,這是對主題的非?;靵y和難以理解的表現。
最后,如果您需要高精度浮點計算,過去20年浮點代碼已經取得了巨大進步,96位和四倍精度浮點數的硬件支持即將到來,但是如果存儲值的操作很重要,那么有很好的任意精度庫。
添加回答
舉報