什么是Mysql浮动?

时间:2016-08-19 20:52:16

标签: mysql precision

这与answer有些相关。我知道浮动不建议高精度。但在完成以下结果后,我并没有完全了解 FLOAT 的内容,

观察1

以下2个查询返回的值会返回不同的结果

SELECT MY_FLOAT_COL FROM MY_TABLE;

SELECT MY_FLOAT_COL*1 FROM MY_TABLE;

可能的解释是上面链接中的引用,它表示float是近似值,问题是数据类型。

观察2

查询

SELECT MY_FLOAT_COL*1 FROM MY_TABLE;

SELECT MY_FLOAT_COL FROM MY_TABLE;
当我使用Squirrel SQL(Java)执行时,

返回相同的结果,但在通过Heidi SQL(Object Pascal)和Python脚本执行时返回不同的结果。因此,这可以得出结论,问题出在客户身上。

Mysql的Float数据类型究竟发生了什么。我试图理解上述2个观察结果。

编辑:我更关心观察2 。我能够从我的观察1 中找到一些意义,但到目前为止后者是神秘的。

2 个答案:

答案 0 :(得分:2)

当您乘以1时,结果将转换为DOUBLE。这具有更高的精度,因此您可以在十进制近似中看到错误。您可以通过将FLOAT列分配到DOUBLE列来查看相同的内容。

CREATE TABLE `my_table` (
  `my_float_col` float,
  `my_double_col` double
);
INSERT INTO my_table (my_float_col) values (1.2355);
UPDATE my_table SET my_double_col = my_float_col;
SELECT my_float_col, my_double_col, my_float_col * 1 FROM my_table;
+--------------+--------------------+--------------------+
| my_float_col | my_double_col      | my_float_col * 1   |
+--------------+--------------------+--------------------+
|       1.2355 | 1.2354999780654907 | 1.2354999780654907 |
+--------------+--------------------+--------------------+

我不确定为什么它会从乘法中返回DOUBLE,因为documentation说:

  

如果+-/*%的任何操作数是实数或字符串值,则精度为result是具有最大精度的操作数的精度。

但显然正在发生的事情。

答案 1 :(得分:2)

发生的事情可以通过稍微修改Barmar的答案来解释,我的答案如下:

drop table if exists my_table2;
CREATE TABLE `my_table2` (
  `my_float_col` float(18,16), -- FLOAT(M,D)
  `my_double_col` double(18,16)
);
INSERT INTO my_table2 (my_float_col) values (1.2355); -- 1.2354999780654907
UPDATE my_table2 SET my_double_col = my_float_col;
SELECT my_float_col, my_double_col, my_float_col * 1 FROM my_table2;
+--------------------+--------------------+--------------------+
| my_float_col       | my_double_col      | my_float_col * 1   |
+--------------------+--------------------+--------------------+
| 1.2354999780654907 | 1.2354999780654907 | 1.2354999780654907 |
+--------------------+--------------------+--------------------+

Barmar的float(第1列)是一个C float数据类型,就像我的一样。但是因为他没有指定精度(M,D),C中的内部实现仍然将它固定为C浮点数,我们具有相同的值,但事实却在Barmar中丢失了。只是他的显示宽度使它更圆。请注意我在下面创建的可以显示的功能。

查看这个名为FLOAT and DOUBLE Data Type Representation的幽默的MySQL手册页面,我认为任何钻研它的人都会非常清楚。因为无论如何我们都会成为数学家:

  

现在让我们来看看MySQL参考手册的故事   离开了。

     

以下讨论集中在没有显示的情况   给出宽度和小数。这意味着FLOAT存储为   无论C类型浮点数是什么,还是存储了REAL或DOUBLE [PRECISION]   无论C型双是什么。字段长度由   MySQL代码。

因此,尽管Barmar的第一列输出,它从来没有作为1.2355,并且上面的手册页巧妙而幽默地描述了人们经历过的头撞事。

Helper fcn如果感兴趣:

DROP FUNCTION IF EXISTS returnFloatFromDec;
DELIMITER $$
CREATE FUNCTION returnFloatFromDec(n DECIMAL(18,16))
returns FLOAT
BEGIN
    DECLARE theRet FLOAT;
    SET theRet=n; -- note that CAST can't take a FLOAT
    return(theRet);
END;$$
DELIMITER ;