大于ActiveRecord查询失败浮动?

时间:2013-12-29 21:45:51

标签: sql ruby-on-rails ruby activerecord

我需要在Rails应用程序中计算值的排名。

我在此question

中关注了示例
def rank
  User.where("points > ?", points).count + 1
end

最初我用整数验证它并且它正在工作。但我也需要对花车进行排名。

例如,我有以下值

0.6238564767774734
0.03700210614260772
0.022441047654982744
0.00935025180031852
0.0016195952859973067
0.0010382902478650936
0.0009367068270665785
0.0004916500182958447
0.00016560735047205894

如果我打电话给查询

User.where("points > ?", 0.6238564767774734).count + 1

它返回2.为什么这样,不应该返回0,因为没有比它大的值?此外,具有第四个和第五个值的查询都返回值5。

来自控制台的SQL查询如下:

SELECT `users`.* FROM `users` WHERE (points > 0.623856)
SELECT `users`.* FROM `users` WHERE (points > 0.00935025)
SELECT `users`.* FROM `users` WHERE (points > 0.0016196)

以防万一我也试过长度和大小而不是计数。

有什么问题,我该如何解决?所有帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

它看起来像是一个问题,如何mysql轮浮动和红宝石轮浮动之间的区别。使用decimal而不是float可能是个更好的主意。

另外看看 http://dev.mysql.com/doc/refman/5.0/en/floating-point-types.html

答案 1 :(得分:1)

0.6238564767774734超出了浮动的精度。

你在Postgres中得到什么(我不知道MySQL中的pg_typeof()等价物):

denis=# select pg_typeof(0.6238564767774734);
 pg_typeof 
-----------
 numeric
(1 row)

denis=# select 0.6238564767774734::decimal, 0.6238564767774734::float;
      numeric       |      float8       
--------------------+-------------------
 0.6238564767774734 | 0.623856476777473
(1 row)

最后,Ruby正在使用BigDecimal。与之匹配的MySQL类型(在MySQL中或多或少,因为您需要指定精度)将是decimal类型:

http://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html

要小心MySQL在这种情况下需要精确度:

mysql> select cast(0.6238564767774734 as decimal);
+-------------------------------------+
| cast(0.6238564767774734 as decimal) |
+-------------------------------------+
|                                   1 |
+-------------------------------------+
1 row in set (0.00 sec)

mysql> select cast(0.6238564767774734 as decimal(20,20));
+--------------------------------------------+
| cast(0.6238564767774734 as decimal(20,20)) |
+--------------------------------------------+
|                     0.62385647677747340000 |
+--------------------------------------------+
1 row in set (0.00 sec)

最后,请注意,由于与浮点类型的表示方式相关的舍入问题,如果您坚持使用浮点数并调整条件,您仍会遇到错误:

http://en.wikipedia.org/wiki/Floating_point#Representable_numbers.2C_conversion_and_rounding

(我猜你在某处内部使用了小数,但是在进行比较时,上面提到的与浮点数相关的问题是很好的。)