这与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 中找到一些意义,但到目前为止后者是神秘的。
答案 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 ;