Ruby BigDecimal与MySQL的十进制精度不匹配

时间:2011-01-20 23:20:22

标签: mysql ruby-on-rails-3 decimal precision bigdecimal

我使用Rails 3.0.3在MySQL数据库中存储一些纬度和经度。以下是我用于创建表的迁移的一部分(请注意具有给定精度的十进制值):

create_table :dummies do |t|
  t.decimal :something, :precision => 13, :scale => 10
end

以下RSpec示例应说明它出错的地方。

我使用BigDecimal进行一些计算,结果my_value是一个精度很大的数字(大于迁移中指定的数字)。我将对象存储在数据库中并再次检索它。

将原始值与数据库值进行比较失败,因为它们的精度不同,因此它不再是相同的数字:

it 'should be equals before and after save' do
  my_value = BigDecimal('4.123456789') * 5000 # more precise than defined in the migration
  dummy = Dummy.new(:something => my_value)
  location.save!
  Dummy.first.something.should == dummy.something
end

我理解为什么会发生这种情况(MySQL中的小数精度!= BigDecimal)但是有人能告诉我在将数据写入数据库之前如何限制my_value BigDecimal的精度确保它尊重数据库约束?

谢谢!

2 个答案:

答案 0 :(得分:4)

在mySQL中,使用FLOAT存储这些地理坐标。将它们存储为高精度十进制毫无意义。请记住,1/60的纬度是海里,所以一英尺(约1/3米)约为3微度。 (3E-06)

IEEE单精度浮点(错误)的epsilon约为6e-08

即使你处于179.9996度,GPS和地理编码也不那么详细。

如果您正在制作非常详细的200级地形图或类似的地图,您可能已经知道必须使用高精度投影,如通用横向墨卡托或兰伯特等等,因为您已超出限制近似地球为球体。但是,如果你正在做一个商店查找类型的应用程序,你不需要,不想要,也不能得到那种精确度。

如果必须在Ruby程序中使用decimal,请在存储到mySQL之前转换为float。

答案 1 :(得分:0)

我会尝试像

这样的东西
new_value = number_with_precision(your_value.to_f, :precision => 13)