ActiveRecord其中Float == Float返回空数组

时间:2016-07-17 15:09:39

标签: ruby-on-rails

有人可以帮助我理解为什么使用where搜索Float匹配的工作方式如下:

> latitude = 37.9763

  37.9763

> Branch.first.latitude
  # Branch Load (0.4ms)  SELECT  `branches`.* FROM `branches`  ORDER BY `branches`.`id` ASC LIMIT 1

  37.9763

> Branch.first.latitude.class

  Float < Numeric

> latitude.class

  Float < Numeric

> Branch.where(latitude: latitude)
  # Branch Load (11.7ms)  SELECT `branches`.* FROM `branches` WHERE `branches`.`latitude` = 37.9763

  []

我还尝试了Branch.where("latitude = ?", latitude),但获得了[]

我一定是在失去理智。

> Branch.where('latitude = ?', Branch.first.latitude) 
  # Branch Load (0.4ms)  SELECT  `branches`.* FROM `branches`  ORDER BY `branches`.`id` ASC LIMIT 1
  # Branch Load (11.3ms)  SELECT `branches`.* FROM `branches` WHERE (latitude = 37.9763)
  []

对于任何好奇的人,我只能使用以下内容在2000个分支中找到3个no match个案例来查找重复项

hash = Branch.group(:business_name, :latitude, :longitude).count
hash.select{|k,v| v > 1}.each do |groupings, count|
  business_name = groupings[0]
  latitude = groupings[1]
  longitude = groupings[2]
  branches = Branch.where(
    business_name: business_name,
    latitude: (latitude - 0.0001)..(latitude + 0.0001),
    longitude: (longitude - 0.0001)..(longitude + 0.0001)
  )
  puts "#{business_name} Count = #{count}"
  puts "#{business_name} Branch Count = #{branches.count}"
  puts "no match" if count != branches.count
end

1 个答案:

答案 0 :(得分:1)

由于floating point numbers are represented的原因,可能会发生这种情况。通过使用正常的相等比较,无法可靠地比较它们。而不是检查完全匹配,最好在比较它们之前检查数字是否在一个范围内或将两个数字四舍五入到一定的精度。

关于具有地理坐标的特定示例(我假设这是因为使用了latitude),我建议使用decimal列类型而不是float

如果您想坚持float列,我可以建议检查值是否在某个范围内,例如:

Branch.where("latitude > ? AND latitude < ?", latitude - 0.00001, latitude + 0.00001)

Branch.where(latitude: (latitude - 0.00001)..(latitude + 0.00001))