MySQL 疯狂的(?)浮点行为

标签 mysql floating-point floating-accuracy

在 MySQL 8.0.21 上,我有一个空表 (Tbl),其中有一列:num,类型为 float

我插入一行,其值为 0.1:

INSERT INTO Tbl(num) VALUES(0.1)

我运行以下查询并获得预期值0.1:

SELECT MAX(num) FROM Tbl

现在,我运行一个查询,我认为该查询在语义上与第一个查询等效,并得到0.10000000149011612:

SELECT MAX(IF(TRUE, num, 0)) FROM Tbl

有趣的是,如果没有 MAX,这种行为就不会重现,即以下返回 0.1:

SELECT IF(TRUE, num, 0) FROM Tbl

我知道 float 并不总是能够准确表示,并且我理解为什么算术运算会导致此类问题,但为什么要在 MAX 中使用这个 IF有什么不同吗?

最佳答案

它们返回不同的类型。当您使用 MAX() 时,它将浮点值上采样为 double :

CREATE TABLE T_MAX AS SELECT MAX(IF(TRUE, num, 0)) AS max_num FROM Tbl;

mysql> SHOW CREATE TABLE T_MAX\G
*************************** 1. row ***************************
       Table: T_MAX
Create Table: CREATE TABLE `T_MAX` (
  `max_num` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8


CREATE TABLE T_IF AS SELECT IF(TRUE, num, 0) AS if_num FROM Tbl;

mysql> SHOW CREATE TABLE T_IF\G
*************************** 1. row ***************************
       Table: T_IF
Create Table: CREATE TABLE `T_IF` (
  `if_num` float DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

我们可以在不执行 MAX() 的情况下从 float 转换为 double 并看到相同的效果:

mysql> SELECT CAST(num AS DOUBLE) AS dblnum FROM TBL;
+---------------------+
| dblnum              |
+---------------------+
| 0.10000000149011612 |
+---------------------+

请注意,如果我们将原始存储的 num 设为 double,则不需要进行转换,因此不会更改表示形式。

CREATE TABLE TBL2 (num DOUBLE);

INSERT INTO TBL2 (num) VALUES (0.1);

SELECT MAX(IF(TRUE, num, 0)) AS num FROM TBL2;
+------+
| num  |
+------+
|  0.1 |
+------+

因此,正是 float 到 double 的转换引起了问题。

关于MySQL 疯狂的(?)浮点行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63659098/

相关文章:

php - 使用php从google maps html调用解析json数据到mysql数据库

在 C 中从对数转换为线性并取平均值

math - float 学有问题吗?

java - Java 的 Math.pow 是否对结果进行四舍五入?

Golang 浮点运算

c# - 从连接到远程 MySQL 数据库的 PHP 服务检索/获取数据以显示到我的 ASP.Net Web 应用程序

mysql - 尝试将年份与大学生联系起来

mysql - 如何在不创建B+Tree INDEX的情况下使MySQL字段唯一

c - 我尝试在代码块上执行以下代码,我得到的不是 92.5 的标记,而是 0.000000

android - Qemu,除以零,mxcsr 寄存器