java - 为什么 MySQL 的 float 与 Java 的 float 不同?

标签 java mysql floating-point

我在 MySQL 浮点列中插入浮点值 1223473,当我取回该值时,该值更改为 1223470。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

public class Main {

    public static void main(String[] args) throws Exception {

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        PreparedStatement pstmt = null;

        try {
            // SETUP
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://...");

            stmt = conn.createStatement();
            stmt.execute("DROP TABLE IF EXISTS ttt");

            stmt.execute("CREATE TABLE ttt (value FLOAT)");

            // INPUT VALUE
            float input = 1.223473E6f;
            print(" Input", input);
            pstmt = conn.prepareStatement("INSERT INTO ttt VALUES (?)");
            pstmt.setFloat(1, input);
            pstmt.execute();

            // OUTPUT VALUES
            rs = stmt.executeQuery("SELECT value, "
                    + "AVG(value) as avg, MIN(value) as min, "
                    + "MAX(value) as max, value + 0 as plus, "
                    + "value * 1 as mult, "
                    + "cast(value as decimal) as valcast "
                    + "FROM ttt;");
            rs.next();
            System.out.println();
            print("Output", rs.getFloat("value"));
            print("   AVG", rs.getFloat("avg"));
            print("   MIN", rs.getFloat("min"));
            print("   MAX", rs.getFloat("max"));
            print("    +0", rs.getFloat("plus"));
            print("    *1", rs.getFloat("mult"));
            print("  CAST", rs.getFloat("valcast"));

        } finally {
            if (stmt != null)
                stmt.close();
            if (pstmt != null)
                pstmt.close();
            if (conn != null)
                conn.close();
        }

    }

    private static void print(String name, float value) {
        System.out.println(name + ": " + value + " (0x" 
            + Integer.toHexString(Float.floatToRawIntBits(value)) + ")");
    }

这是输出:

 Input: 1223473.0 (0x49955988)

Output: 1223470.0 (0x49955970)
   AVG: 1223473.0 (0x49955988)
   MIN: 1223473.0 (0x49955988)
   MAX: 1223473.0 (0x49955988)
    +0: 1223473.0 (0x49955988)
    *1: 1223473.0 (0x49955988)
  CAST: 1223473.0 (0x49955988)

使用 MySQL 客户端也可以看到相同的行为。

我无法解释为什么输入值与输出值不同。此外,为什么应用操作会给出正确的值?即使使用其他值,我也会得到相同的行为。例如,如果我使用 1223472 而不是 122473,则输出值将为 1223470。看起来精度丢失。但为什么对其应用操作会准确返回输入值呢?看起来 MySQL 存储的精度比它显示的要高。

这看起来不像人们试图在 float 中放入太多数字的对浮点类型的典型误解:

System.out.println(1223473f == 1223470f);  // gives false
System.out.println(123456789f == 123456791f);  // gives true (too many digits)

最后,我不知道该怎么想......

mysql> create table ttt (value float);
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTO ttt VALUES (1223473);
Query OK, 1 row affected (0.00 sec)

mysql> select * from ttt;
+---------+
| value   |
+---------+
| 1223470 |
+---------+
1 row in set (0.00 sec)

mysql> SELECT * FROM ttt WHERE value = 1223470;
Empty set (0.00 sec)

mysql> SELECT * FROM ttt WHERE value = 1223473;
+---------+
| value   |
+---------+
| 1223470 |
+---------+
1 row in set (0.00 sec)

为什么值会改变?

最佳答案

您正在使用float作为数据类型。您没有足够的精度来表示 1223473.0。根据MySQL documentation, float 还受到“平台或实现依赖性”的影响。 .

将列上的数据类型更改为double(或decimal),这应该可以解决您的问题。请参阅this SQLFiddle进行确认。

聚合函数,如 SUM, AVG, return a doublefloatdouble 值执行时的值。文档中尚不清楚,但我强烈怀疑使用 MINMAX+ 0 时也会出现这种情况或 * 1 也会产生可以“保存结果值”的数据类型。

您应该知道浮点运算应该在tolerance内进行。 (即阈值),也由 MySQL 文档指定。

关于java - 为什么 MySQL 的 float 与 Java 的 float 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46247940/

相关文章:

简单算术的 C++ 和 Octave 结果不同

c++ - 浮点/整数类型转换的可靠溢出检测

java - tomcat隔离webapps

java - 具有传出 UDP 流量是否允许此端口上的传入流量?

php - 静态方法与静态实例

math - float 学有问题吗?

java - 如何告诉 proguard 保留枚举常量和字段

java - 在java中制作我自己的事件的正确方法是什么

mysql - WordPress fatal error - 内存使用

javascript - 如何使用 PHP 格式化 JSON 响应