MySQL(MariaDB)浮点可视化:为什么值四舍五入到数百或数千?

MySQL (MariaDB) float visualization: why are values rounded to hundreds or thousands?

提问人:Alex Poca 提问时间:6/7/2016 最后编辑:Alex Poca 更新时间:6/8/2016 访问量:1661

问:

第一:我是MySql新手,看起来我在这里遗漏了一些重要的东西。

在MySQL数据库中,我的浮点值范围从单位到数十亿。 我花了几天时间试图理解为什么它们都显示不超过 6 个有效数字,而不太有效的数字设置为 0:

即:

select `field` from `table`;
(instead of X -> i get Y)
  1 -> 1
  12 -> 12
  123 -> 123
  1234 -> 1234
  12345 -> 12345
  123456 -> 123456
  1234567 -> 1234570
  12345678 -> 12345700
  123456789 -> 123457000

只有通过一个“技巧”,我才能在某个地方找到可以读取实际值的地方:

select `field`+0.0 from `table`;

我的问题:这种(恕我直言)奇怪行为背后的基本原理是什么?文档中在哪里描述了它? 我发现完全不直观,我看不到正常选择*的真实值(当然是根据IEEE规范近似的),但我需要这个技巧......我在这里错过了什么?

mysql 浮点精度

评论

0赞 eggyal 6/7/2016
您能否展示一个最小的可重现示例,例如复制/粘贴从表创建到数据选择的完整 MySQL 会话?如果那里的输出格式允许演示此问题,甚至可以使用 sqlfiddle 进行演示?
0赞 Alex Poca 6/8/2016
@eggyal,这是最小的示例: sqlfiddle.com/#!9/352bf/1/0 从 ID6 开始,结果四舍五入为 6 个有意义的密码。问题是,默认情况下使用“select *”,我通常会看到四舍五入的值,而不是实际值......我假设有一个命令可以将数据库设置为使用“真实”值,但无法理解这种奇怪的开发人员选择的原因是什么。
0赞 Alex Poca 6/8/2016
刚刚在 SQLfiddle 上尝试过:使用 double 而不是 float 效果很好。
0赞 Alex Poca 6/8/2016
@RyanVincent,我可以想象这种行为与小数点的数量有关,但我发现即使是更改数字的整数边并且默认情况下只保留 6 个有意义的密码也令人震惊。我对 Mysql 的了解很少(我的错,我敢肯定这在每本 mysql 书中都有说明),但我可以假设有很多像我这样的新手没有看到他们使用的数据是完全错误的。
0赞 Alex Poca 6/8/2016
@RyanVincent,我看了一下IEEE754,浮点数的尾数太短了,无法表示超过 6 个精确的数字。

答:

3赞 eggyal 6/8/2016 #1
  • A 有 24 位或(超过 7 位)具有重要意义:存储在 a 中 as (这是 )。当显示为十进制时,客户端可以肯定地知道从第 8 位开始的所有内容都绝对是错误的精度(因为 a 只能存储 7 位十进制精度)。因此,它会丢弃其余部分,留下 .FLOATlog10(224)12345678.910FLOAT10111100011000010100111121234567910FLOAT12345680

  • A 有 53 位,或(几乎 16 位)具有重要意义:存储在 a as 中(即 )。当显示为十进制时,客户端可以肯定地知道从第 16 位开始的所有内容都绝对是错误的精度(因为 a 只能存储 15 位十进制精度)。因此,它会丢弃其余部分,留下 .DOUBLElog10(253)12345678.910DOUBLE101111000110000101001110.11100110011001100110011001101212345678.9000000003710DOUBLE12345678.9000000

添加时,MySQL首先将 up 转换为 .+0.0FLOATDOUBLE

评论

0赞 Alex Poca 6/8/2016
谢谢@eggyal。当我收到你的答案时,我正在写同样的东西。问题是,正如你所指出的,我忽略了IEEE754表示。即使强制使用 +0.0 进行双重转换,我也会读取额外的密码,但由于它们已保存为浮点数,因此当然不精确。谢谢。
0赞 eggyal 6/8/2016
@AlexPoca:实际上,有趣的是,你似乎(不必要地)在此过程中丢失了十进制数字。虽然尾数只占用 23 位存储空间,但最高有效位没有显式存储,因此您实际上确实有 24 位(或 7 位)的重要性,如我的回答中所述。如果只有 23 位有效,则没有足够的信息来保证第 7 位的正确性,因此也必须放弃它。似乎十进制转换错误地假设为 23 位而不是 24 位:一个错误。FLOAT
0赞 Alex Poca 6/8/2016 #2

根据IEEE754,我忽略了浮点数和双精度的表示,这就是这个谜团的答案。

FLOAT(32 位)的尾数为 23 位(8 百万个可能值 => 6 个有意义的数字),其他 9 位用于符号和指数。 DOUBLE(64 位)的尾数为 52 位(一些 4.5e15 可能的值 => 14 个有意义的数字)。

这意味着 Mysql 无法显示不存在的东西(在我的情况下是 FLOAT 大数字)并用零填充“随机”没有意义的数字。