[mysql基础文档]-8-数据类型之浮点数

引言

在储存数据的过程中,经常会遇到一些小数,比如某些商品的价格,这个时候就可以用到本文介绍的浮点数类型了。

文章目录

0×1.单精度浮点数

单精度浮点数的声明语法是float(M,D),使用4字节储存数据,其中M表示浮点数允许的最大长度(小数点前和小数点后的总长度),D表示小数点后精确的位数。

假设声明float(4,2),代表总长度是4的小数,小数点后能储存2位,多出的尾数四舍五入,小数点前能储存4-2=2位,超出会让整个数字变成4位小数能够储存的最大值,即99.99。

请看下面的实例:

					--新建表t5,仅包含一列fl,单精度浮点型,允许最大长度4,精确到小数点后2位显示
					mysql> create table t5(fl float(4,2));

					--插入一个3位小数
					mysql> insert into t5 values(1.23);

					--插入一个4位小数,但小数点后有3位
					mysql> insert into t5 values(1.236);

					--插入一个5位小数,小数点后有3位
					mysql> insert into t5 values(12.236);

					--插入一个4位小数,小数点前有3位,此时报错
					mysql> insert into t5 values(123.2);
					Query OK, 1 row affected, 1 warning (0.01 sec)

					--结果分析,第一条语句完全没有问题,第二条记录因为设定了只允许精确到小数点后2位,所以四舍五入了,第三条语句同样被四舍五入了,相信看到这里,最大的疑问就是为什么最后一条记录,长度是4位,并没有超过限制,插入后却显示了99.99;实际上,float在声明的过程中有一个规定,如果声明了小数点后精确2位,小数后不论有没有2位,都占用两个位置,也就意味着,小数点前面最大长度只能是2位,因为总长度只能是4位,尽管本例中小数点后只有一位数字。

					--理解这一点后,就不难判断,当小数点前面出现3位的时候,实际上加上小数点后的两个名额(不管有没有)都已经是5位的长度,所以整个小数被设定成4位小数能够储存的最大值99.99
					mysql> select * from t5;
					+-------+
					| fl    |
					+-------+
					|  1.23 |
					|  1.24 |
					| 12.24 |
					| 99.99 |
					+-------+

					--注意!在部分数据库中,超出范围会返回错误,数据不会被设置成最大值。
					

P.s:单精度浮点数使用4个字节存储数据,如果声明单精度浮点数的时候不声明范围(不包含括号和括号中的参数),那么默认的储存范围是-3.402823466E+38到-1.175494351E-38、0和1.175494351E-38到3.402823466E+38。

0×2.双精度浮点数

双精度浮点数声明语句是double(M,D),使用8个字节存储数据,使用方法和单精度是完全一样的,唯一不同的是,如果声明双精度浮点数时不声明范围,那么默认允许的范围是-1.7976931348623157E+308到-2.2250738585072014E-308、0和2.2250738585072014E-308到 1.7976931348623157E+308。

这里不再赘述双精度浮点数的使用方法,请参考单精度浮点数的实例部分,将float替换成double即可。

0×3.如何使用decimal类型储存小数

不论使用单精度还是双精度储存浮点数,都不可避免的存在精度损失,为了避免精度损失,最好的做法就是使用decimal类型,decimal类型声明语法Decimal(M,D),同单精度浮点数一样,M声明可存放的小数总长度,D声明小数点后可以精确多少位。

Decimal类型精度范围为 1 到 31;

存储Decimal数据需要的字节数计算公式:总长度/2(舍掉小数)+ 1 ;例如decimal(9,4),所占用的字节为9/2=4.5,直接去掉小数得4,再用4+1=5字节。如果没有为decimal列定义提供精度和小数位值,那么缺省情况下,使用精度值 5 和小数位值 0,因此,默认情况下,需要 3 个字节的存储空间。

单精度浮点数精度损失问题实例:

					--新建表t6,设定两列,第一列float类型,第二列decimal类型,两列支持的最大长度都设定成9,小数点后支持两位
					mysql> create table t6(fl float(9,2),de decimal(9,2));

					--输入数值测试,数值本身并没有超过规定的长度
					mysql> insert into t6 values(1234567.89,1234567.89);

					--float类型末尾出现精度损失,而decimal因为采取了压缩十进制格式存储,所以更加精确
					mysql> select * from t6;
					+------------+------------+
					| fl         | de         |
					+------------+------------+
					| 1234567.88 | 1234567.89 |
					+------------+------------+
					

P.s:对储存较大的浮点数时,建议使用decimal类型储存,至于为什么浮点数的储存会损失精度,请参考计算机原理基础书籍。