2011-01-20 2 views
0

Я храню несколько широт и долгот в базе данных MySQL с помощью Rails 3.0.3. Вот часть миграции я использовал для создания таблицы (обратите внимание, десятичное значение с заданной точностью):Ruby BigDecimal и несоответствие точности десятичной точности 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), но может ли кто-нибудь сказать мне, как я могу ограничить точность файла BigDecimal my_value, прежде чем я напишу его в базу данных, чтобы убедиться, что он соблюдает ограничения базы данных?

Спасибо!

ответ

4

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

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

GPS и геокодирования не так подробно, даже если вы на 179.9996 градусов.

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

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

+0

Спасибо Олли. Проблема в том, что я использую координату для вычислений позже, поэтому я пошел с BigDecimal, думаю, что Floats могут возвращать странные значения здесь, не так ли? Я попробую ваше последнее решение, конвертируя его в поплавки до проверки. – Cimm

+0

@Cimm - поплавки будут отлично работать для этих вычислений. Шутки в сторону. –

+0

Еще раз спасибо! Я пошел на 't.float: latitude,: limit => 51', это использует Float в Rails и сохраняет значение как Double в MySQL. – Cimm

0

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

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

Спасибо Dimitri, кажется, что преобразование в float перед сохранением в базу данных - это путь. Метод number_with_precision - это помощник вида, который нельзя использовать в модели, поэтому я не думаю, что это поможет. – Cimm

Смежные вопросы