数据类型之float、double、decimal的区别

MySQL 中使用浮点数和定点数来表示小数,其中浮点类型有两种,单精度浮点数FLOAT和双精度浮点数DOUBLE;定点类型只有一种就是 DECIMAL。

类型 大小 范围(有符号) 范围(无符号) 用途
FLOAT 4字节 (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 单精度 浮点数值
DOUBLE 8字节 (-1.797 693 134 862 315 7 E+308,-2.225073858507 2014E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 双精度 浮点数值
DECIMAL 对decimal(M,D) ,如果M>D,为M+2否则为D+2 依赖于M和D的值 依赖于M和D的值 小数值

浮点类型和定点类型都可以用(M, D)来表示,其中M表示总共的位数;D表示小数的位数。

浮点数类型FLOAT 和 DOUBLE的取值范围为 M(1~255)和 D(1~30,且不能大于 M-2),在未指定时默认会按照实际的精度(由计算机硬件和操作系统决定)保存。
定点数类型DECIMAL的取值范围是 M(0~65)和 D(0~30),并且0 <= D <= M <= 65。

浮点数相对于定点数的优点是在长度一定的情况下,浮点数能够表示更大的范围;缺点是会引起精度问题,所以在使用浮点数时需要注意,并尽量避免做浮点数比较。

FLOAT、DOUBLE与DECIMAL的区别

FLOAT单精度浮点数占 4 个字节,1个字节占8位,所以FLOAT存储浮点数用32位二进制进行描述。
DOUBLE双精度浮点数占 8 个字节,所以DOUBLE存储浮点数用64位二进制进行描述。

根据ieee二进制浮点数算术标准:
FLOAT单精度小数部分只能精确到后面6位,加上小数点前的一位,即有效数字为7位。
DOUBLE双精度小数部分能精确到小数点后的15位,加上小数点前的一位,有效位数为16位。

因此DOUBLE存储浮点数的精度更高,这里的精度主要取决于小数点后边位数的长度,越长越精确。但是,在程序中一般来说,cpu处理单精度浮点数的速度比处理双精度浮点数快,因为DOUBLE尾数比FLOAT的尾数多, 所以计算起来必然是有开销的。

虽然DOUBLE比FLOAT精度高一些,但两者存储的都是近似值,并不精确。而DECIMAL是精确存储,它是以字符串形式保存的精确数值,所以适合金额、价格等对精度要求较高的财务类型的数据。

CREATE TABLE test1(a FLOAT(10,2),b DOUBLE(10,2),c DECIMAL(10,2));

DESC test1;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| a     | float(10,2)   | YES  |     | NULL    |       |
| b     | double(10,2)  | YES  |     | NULL    |       |
| c     | decimal(10,2) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+

INSERT INTO test1(a,b,c) VALUES(12.34, 12.34,12.34);

SELECT * FROM test1;
+-------+-------+-------+
| a     | b     | c     |
+-------+-------+-------+
| 12.34 | 12.34 | 12.34 |
+-------+-------+-------+

#不论是定点还是浮点类型,如果存储的小数位数超出指定长度,则会四舍五入进行保存
INSERT INTO test1(a,b,c) VALUES(123.456, 123.456,123.456);

SELECT * FROM test1;
+--------+--------+--------+
| a      | b      | c      |
+--------+--------+--------+
|  12.34 |  12.34 |  12.34 |
| 123.46 | 123.46 | 123.46 |
+--------+--------+--------+

#不论是定点还是浮点类型,如果存储的小数位数不足会自动补足
INSERT INTO test1(a,b,c) VALUES(12345.6, 12345.6,12345.6);

SELECT * FROM test1;
+----------+----------+----------+
| a        | b        | c        |
+----------+----------+----------+
|    12.34 |    12.34 |    12.34 |
|   123.46 |   123.46 |   123.46 |
| 12345.60 | 12345.60 | 12345.60 |
+----------+----------+----------+

#浮点类型是近似存储,而定点类型是精确存储
INSERT INTO test1(a,b,c) VALUES(1234567.21, 1234567.21,1234567.21);

SELECT * FROM test1;
+------------+------------+------------+
| a          | b          | c          |
+------------+------------+------------+
|      12.34 |      12.34 |      12.34 |
|     123.46 |     123.46 |     123.46 |
|   12345.60 |   12345.60 |   12345.60 |
| 1234567.25 | 1234567.21 | 1234567.21 |
+------------+------------+------------+

#浮点类型在计算时可能会造成精度损失
CREATE TABLE test2(a1 FLOAT,a2 FLOAT,b1 DOUBLE,b2 DOUBLE,c1 DECIMAL,c2 DECIMAL);

DESC test2;
+-------+---------------+------+-----+---------+-------+
| Field | Type          | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| a1    | float         | YES  |     | NULL    |       |
| a2    | float         | YES  |     | NULL    |       |
| b1    | double        | YES  |     | NULL    |       |
| b2    | double        | YES  |     | NULL    |       |
| c1    | decimal(10,0) | YES  |     | NULL    |       |
| c2    | decimal(10,0) | YES  |     | NULL    |       |
+-------+---------------+------+-----+---------+-------+

INSERT INTO test2 VALUES (3.3,4.4,3.3,4.4,3.3,4.4);

SELECT * FROM test2;
+------+------+------+------+------+------+
| a1   | a2   | b1   | b2   | c1   | c2   |
+------+------+------+------+------+------+
|  3.3 |  4.4 |  3.3 |  4.4 |    3 |    4 |
+------+------+------+------+------+------+

SELECT a2-a1,b2-b1,c2-c1 FROM test2;
+--------------------+--------------------+-------+
| a2-a1              | b2-b1              | c2-c1 |
+--------------------+--------------------+-------+
| 1.1000001430511475 | 1.1000000000000005 |     1 |
+--------------------+--------------------+-------+

如何选择

当需要存储的小数对精度要求不高时,可以选择FLOAT单精度浮点型,可以节省内存空间,提高计算速度。
当需要进行高速数学计算、科学计算、卫星定位计算等对精度要求较高时,可以选择DOUBLE双精度浮点型。
当需要进行精确计算,如工资结算、转账打款等财务类型的数据,可以选择DECIMAL定点型。

猜你喜欢

转载自blog.csdn.net/kejiayuan0806/article/details/113885030