如有疑問請聯系微信:onesoft007
在計算機中,浮點數往往很難精確表示,那么浮點數運算結果也往往難以精確表示。MySQL同樣也存在這個問題,並表現在如下幾個方面。
問題
1、相同的輸入,可能造成不一樣的輸出(受CPU、編譯器等影響)
a)下面是MySQL官方網站給出的例子
mysql>CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);
mysql>INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),
->(2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),
->(2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),
->(4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),
->(5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),
->(6, 0.00, 0.00), (6, -51.40, 0.00);
mysql>SELECT i, SUM(d1) AS a, SUM(d2) AS b
->FROM t1 GROUP BY i HAVING a <> b;
+------+-------+------+ | i | a | b | +------+-------+------+ | 1 | 21.4 | 21.4 | | 2 | 76.8 | 76.8 | | 3 | 7.4 | 7.4 | | 4 | 15.4 | 15.4 | | 5 | 7.2 | 7.2 | | 6 | -51.4 | 0 | +------+-------+------+
當i=1時,a=21.4、b=21.4,本不滿足a<>b這個條件,可是MySQL仍然判定a與b不相等。
b)在本地虛擬機測試時(Centos 6.4 X86_64)
+------+--------------------+------+
| i | a | b |
+------+--------------------+------+
| 1 | 21.400000000000006 | 21.4 |
| 2 | 76.80000000000001 | 76.8 |
| 3 | 7.399999999999999 | 7.4 |
| 4 | 15.399999999999999 | 15.4 |
| 5 | 7.199999999999999 | 7.2 |
| 6 | -51.4 | 0 |
+------+--------------------+------+
2、結果受浮點數本身的精確度影響
把double改成float,結果如下
+------+---------------------+--------------------+
| i | a | b |
+------+---------------------+--------------------+
| 1 | 21.400001525878906 | 21.399999618530273 |
| 2 | 76.79999828338623 | 76.80000114440918 |
| 3 | 7.399999618530273 | 7.400000095367432 |
| 5 | 7.200000762939453 | 7.199999809265137 |
| 6 | -51.400001525878906 | 0 |
+------+---------------------+--------------------+
解決方案
1、decimal
在MySQL中,帶有小數的精確運算可以使用decimal類型
CREATE TABLE t3 (i INT, d1 decimal(10,3), d2 decimal(10,3));
+------+---------+-------+
| i | a | b |
+------+---------+-------+
| 6 | -51.400 | 0.000 |
+------+---------+-------+
限制
decimal的精確表示為decimal(M,D),其中M最大為65,D最大為30。因此其表示的范圍是遠遠小於double所能表示的范圍
2、基於應用的解決方案
比如商品價格涉及到小數,用20.95元表示,那么可以把價格變成以分為單位,即變成2095。
結論
不要使用float、double以及其等價類型做精確計算。如果要在MySQL中做精確計算,推薦使用decimal或者將相關計算任務交給應用。
如有疑問請聯系微信:onesoft007