Несоответствие десятичной точности в Ruby BigDecimal и MySQL - PullRequest
0 голосов
/ 21 января 2011

Я храню некоторые широты и долготы в базе данных MySQL, используя Rails 3.0.3. Вот часть миграции, которую я использовал для создания таблицы (обратите внимание на десятичное значение с заданной точностью):

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 ]

4 голосов
/ 21 января 2011

В mySQL используйте FLOAT для хранения этих гео-координат.Просто не имеет смысла хранить их как десятичные с высокой точностью.Имейте в виду, что 1/60 градуса широты - это морская миля, поэтому фут (~ 1/3 метра) составляет около 3 микродез.(3e-06)

Эпсилон для IEEE с плавающей запятой одинарной точности (ошибка) составляет около 6e-08

GPS и геокодирование не настолько подробны, даже когда вы находитесь на 179,9996градусов.

Если вы создаете очень подробные топографические карты в масштабе 200 или что-то в этом роде, вы, вероятно, уже знаете, что вам нужно использовать высокоточную проекцию, например универсальный поперечный Меркатор, Ламберта или что-то подобное, потому что выВы вне предела приближения Земли как сферы.Но если вы работаете с приложением типа магазина, вам не нужна, не нужна и не может быть такая точность.

Если вы ДОЛЖНЫ использовать десятичную дробь в своемRuby-программа, конвертируйте в float перед сохранением в mySQL.

Вот объяснение точности геокоординат Рэндалла Манро.

enter image description here

0 голосов
/ 21 января 2011

Я бы попробовал что-то вроде

new_value = number_with_precision(your_value.to_f, :precision => 13)
...