【问题标题】:How MySQL does the math calculation of floating point addition?MySQL如何进行浮点加法的数学计算?
【发布时间】:2019-03-25 08:45:17
【问题描述】:

我用SELECT 0.1 + 0.2;测试,用MySQL(MariaDB)查询,它返回了正确的答案

MariaDB [(none)]> SELECT 0.1 + 0.2;
+-----------+
| 0.1 + 0.2 |
+-----------+
|       0.3 |
+-----------+
1 row in set (0.000 sec)

由于IEEE 754here 的解释,浮点计算在大多数编程语言中都不准确。

MySQL 如何进行浮点计算以使其返回正确答案?

【问题讨论】:

  • 在大多数编程语言中它的计算有点错误:你能提供一个无法准确计算0.1 + 0.2 的软件的实际示例吗?
  • @GMB 在 Python 中返回 0.30000000000000004,这里还有很多其他语言的例子 => 0.30000000000000004.com

标签: mysql sql ieee-754


【解决方案1】:

我知道 SQL 92 是旧标准,但我很确定这在较新的 SQL 标准版本中没有改变。

SQL 92 定义

73)Subclause 6.12, "<numeric value expression>": 当数据类型 加法的两个操作数。减法,乘法, 或除法运算符是精确数字,则 结果是实现定义的。"*

75)Subclause 6.12, "<numeric value expression>": 当数据 算术运算符的 either 操作数的类型是 近似的 numeric,结果的精度是实现定义的。"*

问题是:0.10.2 在查询 SELECT 0.1 + 0.2 中是近似值还是精确值?
答案是:你不知道,数据库也不知道。
所以数据库将运行为 MySQL 和 MariaDB 引擎定义的实现,这个接缝被处理为 DECIMAL(1,1) 数据类型

为什么尼克的答案会返回正确的值或带有表定义的预期值

SQL 92 也定义了

隐式类型转换可以发生在表达式中,取Opera-
、单行选择操作、插入、删除和更新。
可以使用 CAST 指定显式类型转换
运算符。

Nick 通过在表中定义数据类型来完成的。

编辑了这个答案,因为我今天在 MySQL 的手册中找到了一些东西。

查询

SELECT (0.1 + 0.2) = 0.3

结果为 MySQL 中的 1,这意味着 MySQL 使用精确的数字计算并在可能的情况下使用 Precision Math。 所以 MySQL 确实知道 0.10.20.3 是这里的精确数据类型,需要精确计算,就像我在这次编辑之前所期待的那样。

查询的意思

SELECT (0.1 + 0.2) = 0.3 

将在引擎盖下运行或多或少像

SELECT CAST((0.1 + 0.2) AS DECIMAL(1, 1)) = CAST((0.3) AS DECIMAL(1, 1));

【讨论】:

  • @DarkSuniuM 今天在 MySQL 手册中发现了一些新内容,我已经编辑了问题
【解决方案2】:

这只是 MySQL 在数据类型/格式选择方面的智能,因为您没有指定这些值是浮点数。试试这个:

create table test (f float);
insert into test values (0.1), (0.2);
select sum(f) from test

输出:

sum(f)
0.30000000447034836

Demo on dbfiddle

如果你使用双精度,你会得到经典的0.30000000000000004 结果。 Demo on dbfiddle

【讨论】:

  • 似乎是对的,你能解释一下它是如何智能的吗?这对我来说很重要,谢谢
  • @DarkSuniuM 不幸的是,我对 MySQL 的内部结构并不熟悉。我怀疑它只是选择使用DECIMAL 来确保准确性。
  • “我对 MySQL 的内部结构不太熟悉。我怀疑它只是选择使用 DECIMAL 来确保准确性。” 事实上@Nick 已经确认(刚刚在手册中找到它)MySQL使用精确的数字计算其中possible
  • @RaymondNijland 感谢您的更新。很高兴得到确认 - 我想我应该更加努力地狩猎。如果我能再次支持你的答案,我会的! :-)
猜你喜欢
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多