【问题标题】:MySQL floating point comparison issuesMySQL浮点比较问题
【发布时间】:2011-02-03 18:38:41
【问题描述】:

我在 MySQL 数据库架构中引入浮点列时遇到了一个问题,即浮点值的比较并不总是返回正确的结果。

1 - 50.12
2 - 34.57
3 - 12.75
4 - ...(休息时间小于 12.00)

SELECT COUNT(*) FROM `users` WHERE `points` > "12.75"

这返回“3”。

我读到 MySQL 中浮点值的比较是一个坏主意,而十进制类型是更好的选择。

我是否有希望继续使用浮点类型并使比较正常工作?

【问题讨论】:

  • SQL中双引号括起来的字面量有哪些?
  • 不幸的是,MySQL 默认允许双引号像单引号一样工作。可以使用 ANSI_QUOTES 选项关闭此功能,这将使它们根据 ANSI SQL 标准引用标识符(如上述查询中的非标准反引号)。
  • 12.75 完全可以用二进制 (1100.11) 表示,所以我看不出它如何通过测试 "> 12.75"。您确定您的列表中没有其他点 > 12.75 吗?

标签: mysql comparison floating-point select-query


【解决方案1】:

你注意到下面的问题了吗?

CREATE TABLE a (num float);

INSERT INTO a VALUES (50.12);
INSERT INTO a VALUES (34.57);
INSERT INTO a VALUES (12.75);
INSERT INTO a VALUES (11.22);
INSERT INTO a VALUES (10.46);
INSERT INTO a VALUES (9.35);
INSERT INTO a VALUES (8.55);
INSERT INTO a VALUES (7.23);
INSERT INTO a VALUES (6.53);
INSERT INTO a VALUES (5.15);
INSERT INTO a VALUES (4.01);

SELECT SUM(num) FROM a;
+-----------------+
| SUM(num)        |
+-----------------+
| 159.94000005722 | 
+-----------------+

在其中一些行之间有一个额外的0.00000005722。因此,与初始化它们的值相比,其中一些值将返回 false。

为避免浮点运算和比较出现问题,您应该使用DECIMAL 数据类型:

ALTER TABLE a MODIFY num DECIMAL(6,2);

SELECT SUM(num) FROM a;
+----------+
| SUM(num) |
+----------+
|   159.94 | 
+----------+
1 row in set (0.00 sec)

【讨论】:

  • 嘿丹尼尔!谢谢。我正在考虑将我的列类型转换为 DECIMAL。
  • @Sharief:如果无法转换为DECIAML,我看到的唯一选择是允许浮点比较有一定的容差,这样您就可以编写如下查询:SELECT COUNT(*) FROM users WHERE points > (12.75 + 0.001);.. . 然而,如果准确性是最重要的,固定点DECIMAL 是要走的路。 DECIMAL 的另一种替代方法是使用按比例放大的整数值以百分之一表示您的值:5012 而不是 50.12。在某些情况下,这可能是合适的。
  • 我确实尝试过添加容差,完全按照您提到的方式,即使那样结果也始终不一致。
  • DECIMAL 并非在所有情况下都是正确的选择...阅读此内容:stackoverflow.com/a/5150314/655224。就我而言,我将两个浮点值与...WHERE CAST(float1 AS CHAR) <= CAST(float2 AS CHAR)? 进行了比较
【解决方案2】:

我这样做

WHERE abs(value - 12.75)<0.001

但我同意,任何语言都可以比较浮点相等性,如果存储的值等于您插入的确切数字值,则应该没有任何问题

只有几个小数和精确匹配的值,精度错误听起来不像是 MySQL 中这种不匹配的明显原因

【讨论】:

    【解决方案3】:

    我曾经遇到过类似的问题。将“浮点”字段转换为“十进制”。肯定能解决问题。

    【讨论】:

    • 我认为通过使用精确的固定长度的浮点数已经解决了问题,所以它没有??例如;我定义浮点数(4,2)。然后我存储了 12.50 的值,然后我尝试将它与“> 12.50”语句进行比较。不会还是失败吗?
    【解决方案4】:

    在比较浮点数是否相等时存在问题。这可能会产生意想不到的结果。这是由于浮点运算的内部实现。

    【讨论】:

      【解决方案5】:

      这是一个浮点数,有什么问题吗? 3 可能是正确的结果,取决于数据库对 12.75 的看法。是 12.75 还是更多?

      如果您想要精确的数字,请使用 DECIMAL。

      【讨论】:

      • 嗨弗兰克,您能否详细说明“数据库对 12.75 的看法”是什么意思。如果我试图将两位精度值与三位精度进行比较,我会遇到麻烦吗?喜欢... SELECT COUNT(*) FROM users WHERE points > "12.751"
      • @ShariefShaik 我认为 Decimal 应该从其他用户体验中解决这种情况。
      【解决方案6】:

      比较数字和字符串?

      【讨论】:

        【解决方案7】:

        使用 REAL 而不是 FLOAT 或 DECIMAL。

        【讨论】:

          【解决方案8】:

          小数比较不适用于FLOAT 数据类型值。您只需要将列数据类型更改为DECIMAL

          ALTER TABLE a MODIFY num DECIMAL(6,2);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-10-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-12-09
            相关资源
            最近更新 更多