MYSQL如何在内部表示浮动?

MYSQL如何在内部表示浮动?,mysql,sql,floating-point,Mysql,Sql,Floating Point,我遇到了这个问题,在浮点列中插入一个像1234567这样的数字会导致1234570的舍入值 我知道这是由于浮点精度,但让我困惑的是,如果我使用上面的浮点列进行一些计算,那么它将使用实际值(1234567) 如果我在列上使用Select语句,它会给出舍入值, 但如果我将它转换为十进制,或者对它执行一些计算,它会使用实际值 所以我的问题是,是什么让MySQL这样做的 编辑: 例如: select cast(1234567 as float), cast(1234567 as float) + 1

我遇到了这个问题,在浮点列中插入一个像1234567这样的数字会导致1234570的舍入值

我知道这是由于浮点精度,但让我困惑的是,如果我使用上面的浮点列进行一些计算,那么它将使用实际值(1234567)

如果我在列上使用Select语句,它会给出舍入值, 但如果我将它转换为十进制,或者对它执行一些计算,它会使用实际值

所以我的问题是,是什么让MySQL这样做的

编辑:

例如:

select cast(1234567 as float), cast(1234567 as float) + 1
返回:

1234570 1234568

你关于浮点精度的问题并不仅仅局限于MySQL,对于任何数据库或编程语言来说,这都是一个有效且类似的问题。底线是,由于浮点数在内部的表示方式,它们并不精确,使用浮点数进行的运算也不精确

如果您需要精确的精度,那么您应该使用精确的类型,例如
数字
十进制
,根据我们可以在您的小提琴中获得数据类型,它显示(我在8.0.20/FreeBSD/i386下运行):

因此,它的规则类型在一种情况下导致
float
,在另一种情况下导致
double
。1234567完全用浮点表示,但截断请参见下文

实验表明,CAST(AS float)在标记为float时提供float64浮点值(
double
,在C中),但只有在最后放入存储的DB单元时,实际值才被切割为float32。但是,使用“+”,float在添加之前转换为double,这在addition操作符类型result中表示,因此,自动创建将公开
double
。但如果声明的类型仍然是float,MySQL不仅会将其截断为float32,还会将其四舍五入为6个默认的可打印数字:(

我在MySQL文档中找不到这些细节(要么省略了,要么我对这种文档风格的挖掘技巧很差),但是这种方法(除了剪切成文本形式)至少符合应用于C/C++的常识方式。它们允许在放入输出变量之前有更广泛的浮点值中间表示


因此,
CAST()
在8.0中是新的(5.7不支持
float
double
在CAST中),这可能是太原始的实现。请随时向MySQL开发人员投诉,要求他们升级到适当的MODU。

是的,我确实理解浮点不准确不仅限于MySQL,但您可以解释上述行为。我只是想知道,如果您将文字值转换为确切的ty,进行转换如何为实际值pe,那么它是精确的,你做的任何算术也会是精确的,这是基本的解释。这是一个非常好的问题,但没有例子就不清楚。我几乎无法推测发生了什么。这就好像
cast()
在算术表达式中与独立表达式中的解释不同。
netch@localhost [test]> create temporary table t1 select cast(1234567 as float), cast(1234567 as float) + 1, cast(12345678 as float) + 1;
netch@localhost [test]> show create table t1;
+-------+---------------------------------------------------------------------->
| Table | Create Table                                                         >
+-------+---------------------------------------------------------------------->
| t1    | CREATE TEMPORARY TABLE `t1` (
  `cast(1234567 as float)` float NOT NULL DEFAULT '0',
  `cast(1234567 as float) + 1` double NOT NULL DEFAULT '0',
  `cast(12345678 as float) + 1` double NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+---------------------------------------------------------------------->
1 row in set (0.00 sec)