我知道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)
irb(main):004:0> Url.find_by(url_md5: 'noop').gcloud_magnitude.to_f
=> 6.1
答案 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个字节可以处理的精度高,因此它如何存储原始表示形式?
与该原始问题无关的更多问题。