-FLOAT,DOUBLE:
FLOAT和DOUBLE类型代表近似数字数据值。MySQL将四个字节用于单精度值,并将八个字节用于双精度值。
对于FLOAT,SQL标准允许对FLOAT括号中的关键字后面的位以精度(而不是指数的范围)进行可选规范 ;; 即 。MySQL还支持此可选的精度规范,但是in的精度值 仅用于确定存储大小。从0到23的精度导致4字节单精度 列。从24到53的精度导致8字节的双精度列。 FLOAT(p)FLOAT(p)FLOATDOUBLE
-- 创建表,还有float和double字段:
CREATE TABLE F_02 (i INT, a FLOAT, b DOUBLE);
-- float插入多位数可看到小数位被省略,由此可看到“浮点值是近似值而不是作为精确值存储的”
insert into f_02 (i,a,b) values (3,100000.001,200000.002);
MySQL允许使用非标准语法: 或 或。在此, 平均值最多可以存储最多 位数,其中 位数可以在小数点后。例如,定义为的列 在显示时看起来像 。MySQL在存储值时执行四舍五入,因此,如果将其插入 到 列中,则近似结果为 。 FLOAT(M,D)REAL(M,D)DOUBLE PRECISION(M,D)(M,D)MDFLOAT(7,4)-999.9999999.00009FLOAT(7,4)999.0001
-- 创建表,并设置float小数位:
CREATE TABLE F_03 (a FLOAT(5,3));
-- 插入数据,查看四舍五入数据:
INSERT INTO F_03 (a) VALUES (10.01),(10.001),(10.0001),(10.0006);
由于浮点值是近似值而不是作为精确值存储的,因此在比较中尝试将它们视为精确值可能会导致问题。它们还受平台或实现依赖性的约束。有关更多信息,请参见 第B.3.4.8节“浮点值的问题”
为了获得最大的可移植性,需要存储近似数值数据值的代码应使用FLOAT或 DOUBLE PRECISION不指定精度或位数。
浮点值的问题:
浮点数有时会引起混淆,因为它们是近似值而不是作为精确值存储的。SQL语句中编写的浮点值可能与内部表示的值不同。尝试在比较中将浮点值视为精确值可能会导致问题。它们还受平台或实现依赖性的约束。该 FLOAT和 DOUBLE数据类型都受到这些问题。对于DECIMAL 列,MySQL执行的精度为65位十进制数字,这应该可以解决最常见的不准确性问题。
下面的示例用于 DOUBLE演示使用浮点运算完成的计算如何受到浮点误差的影响。
-- 创建表
CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);-- 插入数据
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);-- 按照序号分组统计a不等于b的数据
SELECT i, SUM(d1) AS a, SUM(d2) AS bFROM t1 GROUP BY i HAVING a <> b;
-- 统计结果
结果是正确的。虽然前五记录看起来他们不应该满足的比较(值 a和b似乎没有不同),他们可以这样做,因为周围的第十小数左右的数字显示之间的差异,这取决于多种因素,如计算机体系结构或编译器版本或优化级别。例如,不同的CPU可能会不同地评估浮点数。
如果将列d1和d2定义为DECIMAL而不是DOUBLE,则SELECT查询结果 将只包含一行,即上一行。
进行浮点数比较的正确方法是,首先确定数字之间差异的可接受公差,然后再与公差值进行比较。例如,如果我们同意,如果浮点数在千分之一(0.0001)的精度内相同,则应将它们视为相同,那么应进行比较以找出大于公差值的差异:
-- ABS()函数是一种数学函数,其作用是返回给定数字的绝对值。
SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM F_01 GROUP BY i HAVING ABS(a - b) > 0.0001;
-- 结果
相反,要获得数字相同的行,测试应在公差值内找到差异:
SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM F_01 GROUP BY i HAVING ABS(a - b) <= 0.0001;
-- 结果
浮点值取决于平台或实现的依赖性。假设您执行以下语句:
CREATE TABLE t1(c1 FLOAT(53,0), c2 FLOAT(53,0));
INSERT INTO t1 VALUES('1e+52','-1e+52');
SELECT * FROM t1;
在某些平台上,该SELECT语句返回inf和-inf。在其他对象上,它返回0和 -0。
前述问题的含义是,如果尝试通过在源上使用mysqldump转储表内容并将转储文件重新加载到副本中来创建 副本,则两个主机之间包含浮点列的表可能会有所不同。