mysql如何在内部表示浮动?

wqsoz72f  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(472)

我遇到了这个问题,在float列中插入一个像1234567这样的数字会导致1234570的舍入值。
我知道这是由于浮点精度造成的,但让我困惑的是,如果我使用上面的浮点列进行一些计算,那么它将使用实际值(1234567)。
如果我只是在列上使用select语句,它会给出舍入值,但是如果我将它转换为decimal或对它执行一些计算,它会使用实际值。
所以我的问题是,是什么让mysql这样做的?
编辑:
例如:

select cast(1234567 as float), cast(1234567 as float) + 1

退货:

1234570 1234568

这是一把小提琴。

k4emjkb1

k4emjkb11#

关于浮点精度的问题并不仅仅局限于mysql,它对于任何数据库或编程语言都是一个有效且类似的问题。归根结底,由于浮点数在内部的表示方式,它们并不精确,用浮点数进行的运算也不精确。
如果您需要精确的精度,那么应该使用精确的类型,例如 NUMERIC 或者 DECIMAL .

gev0vcfq

gev0vcfq2#

根据配方,我们可以在您的fiddle中获得数据类型,它显示(我在8.0.20/freebsd/i386中运行):

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)

所以它的规则类型会导致 float 在一个案例中 double 在另一种情况下。1234567用float表示,但是,请参见下面的截断。
实验表明,cast(as float)提供float64浮点值( double 在c)标记为float,但实际值仅在最后放入存储的db单元时切为float32。但是,对于'+',float在加法之前被转换为double,这在加法运算符类型result中表示,因此,自动创建将公开 double . 但如果声明的类型仍然是float,mysql不仅会将其截断为float32,还会将其舍入为6个默认的可打印数字:(
我在mysql文档中找不到这些细节(要么省略了,要么我对这种文档样式的挖掘技巧不好),但这种方法(除了剪切成文本形式)至少符合应用于c/c++的常识方式。它们允许在放置到输出变量之前有更广泛的浮动值中间表示。
像这样的 CAST() 是8.0的新功能(5.7不支持 float 以及 double 在cast中),这可能是太原始的实现。请随时向mysql开发人员投诉,以提高到一个适当的模式。

相关问题