1

从 rails 控制台工作,为什么以下find_by返回 nil?

2.0.0 (main):0 > Location.last
  Location Load (0.8ms)  SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT 1
=> #<Location id: 92, district: nil, address: "8026 S KEDZIE AVE", city: "CHICAGO", state: "IL", zip: 60652, website: nil, location: nil, latitude: 41.7474748619454, longitude: -87.7023800625442, location_type: "fire_station">
2.0.0 (main):0 > lat = Location.last.latitude
  Location Load (0.8ms)  SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT 1
=> 41.7474748619454
2.0.0 (main):0 > Location.find_by( latitude: lat)
  Location Load (0.8ms)  SELECT "locations".* FROM "locations" WHERE "locations"."latitude" = 41.7474748619454 LIMIT 1
=> nil

我最初认为这与 Sqlite 有关,所以我切换到 Postgres 但仍然产生相同的结果。从事某个项目的其他人运行相同的操作find_by产生了正确的结果。我的系统发生了什么情况?

4

2 回答 2

2

假设这是平等检查的问题,以下是来自http://www.mail-archive.com/rubyonrails-talk@googlegroups.com/msg02703.htmlFloat的一些建议:

给定: x = 11.967 y = 11.966999999999 <-- 由于十六进制<->十进制转换导致精度损失

  1. 根据一个范围(如前一篇文章中所建议的)11.9670 <= x < 11.968 进行比较。

  2. 比较浮点值的字符串表示形式:x == y => false ("%.3f" % x) == ("%.3f" % y) => true

  3. 使用定点数据类型存储值(如 MySQL 中的 DECIMAL): lng DECIMAL(5,3) x -> lng => 11.967 y -> lng => 11.967 <--根据数据库中定义的规则进行四舍五入比较两个值的相等性是安全的

  4. 将固定十进制值作为整数存储在数据库中,并在显示时进行转换。我只提到这种技术是因为它是存储货币价值的一种选择。与其存储美元,不如存储美分并通过在视图上显示值转换为美元。$1.60 -> 160(在数据库中)

于 2013-11-13T02:53:32.480 回答
0

作为一种快速解决方法,您可以使用 SQLROUND方法

Location.find_by("ROUND(latitude, 3) = ?", "%.3f" % lat)

但它会有效地杀死你在位置表上的索引(假设你有一个)并且并不真正适合大量数据。

于 2013-12-06T00:58:08.377 回答