MySQL为什么将float 6.099999904632568截断为6.1

时间:2018-09-16 16:20:38

标签: mysql activerecord floating-point

我知道float是一个近似值,具体取决于所需的精度。但是,我对为什么将6.099999904632568转换为6.1感到困惑。为什么需要四舍五入而不是以其最大精度停止(即6.09999990

无论如何,我是否可以强制数字以最大精度存储而不舍入?

表格信息

CREATE TABLE `urls` ( `id` int(11) NOT NULL AUTO_INCREMENT, `gcloud_magnitude` float DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1193 DEFAULT CHARSET=utf8;

要复制的代码

mysql> INSERT INTO urls (url_md5, gcloud_magnitude, created_at, updated_at) VALUES ('noop', 6.099999904632568, '2018-09-16 14:57:49', '2018-09-16 14:57:49'); Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM urls WHERE url_md5 = 'noop'\G; id: 1193 url_md5: noop gcloud_magnitude: 6.1 1 row in set (0.00 sec)

Ruby解释器解析为float

irb(main):004:0> Url.find_by(url_md5: 'noop').gcloud_magnitude.to_f => 6.1

3 个答案:

答案 0 :(得分:3)

您看到的值6.1可能是所谓的roundtrip输出。这是解析后的最短输出,它将返回与原来相同的值。并非所有语言都将输出作为往返来回浮动或加倍,但是有些语言会这样做,除非另有明确说明。我猜Ruby是其中之一。

将值6.1解析为float时,将获得精确的值6.099999904632568359375,但是将值6.099999904632568解析为浮点时,将获得完全相同的值。 6.1是可为该特定float生成的最短输出,当回读(再次解析)时,它将生成相同的float。

答案 1 :(得分:0)

MySQL中的FLOAT数据类型没有足够的精度来存储您提供的值。 DOUBLE数据类型可以做到这一点。

示例:

mysql> create table f ( f float, d double);

mysql> insert into f values (6.099999904632568, 6.099999904632568);

mysql> select * from f;
+------+-------------------+
| f    | d                 |
+------+-------------------+
|  6.1 | 6.099999904632568 |
+------+-------------------+

FLOAT将值四舍五入到可以存储的精度。实际上,即使使用精度比您使用的值低的值,也会发生舍入。

mysql> select * from f;
+---------+-------------------+
| f       | d                 |
+---------+-------------------+
|     6.1 | 6.099999904632568 |
|     6.1 |         6.0999999 |
|     6.1 |          6.099999 |
| 6.09999 |           6.09999 |
+---------+-------------------+

32位FLOAT中没有足够的位来存储无限精度。因此必须舍入该值。

您会发现DOUBLE的精度也受到限制。它以64位格式存储值。

答案 2 :(得分:-1)

我想总结一下我的发现作为答案。

当我将诸如6.099999904632568之类的值保存到float数据类型中时,MySQL将其表示为6.1。当我将数据类型更改为decimal with precision 64 and scale 30时,将自动显示6.099999904632568,而无需更新值。

似乎MySQL确实保存了数字的原始表示形式,但是没有办法将该值作为浮点数返回。当我将数据类型切换为十进制时,MySQL知道如何正确表示它并正确返回它。

这让我感到困惑。如果MySQL知道原始表示形式,为什么我不能在不将其类型转换为浮点数的情况下取回原始值。另外,由于6.099999904632568的精度比4个字节可以处理的精度高,因此它如何存储原始表示形式?

与该原始问题无关的更多问题。