浮点数和定点数
这两者都是用来表示小数的,浮点数包括float(单精度)、double(双精度),定点数为decimal。两者在定义时都可以指定其精度和标度,精度是指一共显示多少位数字(整数位+小数位),标度是指精确到小数点后多少位,表现形式如:decimal(15,2),这里的精度是15位(整数13位,小数2位),标度是2位。
需要说明的是定点数在MySQL内部是以字符串的形式来保存的,属于准确存储,
我们创建一张表,字段id的数据类型为decimal(5,2)
向表里插入超过标度的值时,虽然插入成功但是MySQL有一个警告,查看数据我们知道发生了四舍五入。
我们再向表里尝试插入超过精度的值,难道也会发生截断并四舍五入?两个值会分别显示为123.12和124.12吗?从结果来看明显不是,我们的猜测是完全错误的。在超过精度的情况下,虽然插入成功但插入的值却是指定精度和标度下的最大值,例如(5,2)下的最大值为999.99。
若是在SQL Mode严格模式下,上述这些插入操作将不能被执行成功且MySQL会报ERROR。
额外知识点:
如何理解单精度和双精度?
这两者的区别如果理解为“单精度是精确到小数点后一位,而双精度是精确到小数点后两位”,那就大错特错了。实际上由于float的有效位数是7位,double的有效位数是16位,因此单精度、双精度其实是指代这里的有效位数。
另外需要注意的是有效位数并不等于精确位数,纵然float可以表示到小数点后7位,但只有前6位是精确的,第7位很可能造成数据误差。而对于double来说只有前15位是精确的,第16位也很可能造成数据误差。
额外知识点:
关于float、double精度丢失的问题,实际上就是被扩展或截断了,究其缘由是因为存取时标度不一致所导致的。在录入数据时若数据的标度与定义列数据类型时设置的标度不一致,则会导致存入时以近似的值来存储,这就造成了我们上面说到的精度丢失。
那在什么情况下float、double的精度不会丢失呢?其实根据上面出问题的情况,我们可以想到当数据标度与类型标度一致时(录入数据的标度与定义列数据类型时设置的标度一致),就不会发生精度丢失。
鉴于此,我们常选用decimal类型,小于等于其标度的数据都能被正确录入,不会发生精度丢失,因为其是将数据以字符串的形式来存进数据库的,这就保证了精确性。但并不是说decimal就不会发生精度丢失,因为它虽然不会发生精度扩展但却会发生精度截断,例如当录入数据的标度大于列数据类型设置的标度时,依然会发生四舍五入。
虽然我们说decimal将数据以字符串的形式存入数据库,同时又会存在精度截断的问题(四舍五入),看似两者有文字描述上的冲突,其实不然。我们这样来理解:decimal将发生了四舍五入的数据以字符串的形式存入了数据库,但表现出来的是小数(一个是存储形式,一个是表现形式),且这个小数的精度不会再发生变化,而不管是以什么精度来获取这个值,它都是四舍五入后以字符串形式存入时的值。