我需要在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)
以防万一我也试过长度和大小而不是计数。
有什么问题,我该如何解决?所有帮助表示赞赏。
答案 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
(我猜你在某处内部使用了小数,但是在进行比较时,上面提到的与浮点数相关的问题是很好的。)