olliej's округление метод является неправильным при отрицательных числах
, Вот альтернатива
int myInt = (int)(myDouble + (myDouble>0 ? 0.5 : -0.5))
, Вы могли, конечно, использовать округляющуюся функцию от math.h
Лично я бы использовал 32-битное десятичное представление с фиксированной запятой, разделив на 1000000 в соответствии с ответом Эвана и моими комментариями.
Однако, если пространство действительно ограничено, вот некоторые дополнительные идеи:
Вы можете использовать 26-битное представление с фиксированной точкой на проводе. Это потребует маршалинга и демаршалинга широты и долготы в большой массив байтов, но сэкономит вам 12 бит для каждого местоположения по сравнению с 32-битным представлением значения - почти 19% экономии, так что это вполне может оказаться стоящим.
могли бы воспользоваться тем фактом, что для значений долготы требуется меньшая точность по мере приближения к полюсам - им нужно всего 26 бит на экваторе. Таким образом, вы можете написать схему, в которой количество битов, используемых для кодирования долготы, зависит от значения широты.
Если ваши данные имеют другие сжимаемые атрибуты - скажем, все точки обычно расположены довольно близко друг к другу - вы можете воспользоваться конкретным преимуществом из них, например, используя схему дельта-кодирования (где каждая точка, кроме первой, может быть закодирована как дельта из последнего пункта).
Окружность Земли составляет прибл. 40 000 км или 24900 миль.
Вам нужна точность в один метр (3 фута), чтобы иметь возможность превосходить точность GPS на порядок.
Следовательно, вам нужна точность для хранения 40 000 000 различных значений. Это минимум 26 бит информации. Подойдет 32-битное число с плавающей запятой или int.
Поплавков было бы более чем достаточно для хранения координат GPS, даже если бы устройства GPS потребительского уровня имели точность, близкую к заявленной для них. . Если вы не верите, что это правда, попробуйте эти два простых эксперимента:
Я писал приложения для GPS -подключенные КПК в течение многих лет, и я проверял это на сомнительных покупателях снова и снова (я даже выигрывал пари таким образом). Существуют более качественные устройства GPS, которые обеспечивают лучшую точность, чем эта, но лучшая точность достигается с более дорогими наборами микросхем, и устройства остаются на одном месте в течение нескольких дней или даже недель, с усреднением показаний по времени.
Четырехбайтовое число с плавающей запятой намного точнее, чем сами устройства . Конечно, вам совсем не повредит использовать вместо него двойной, если множитель 2Х для вас не проблема.
23 бита точности на 179 градусах долготы дают точность менее 10 метров, что является лучшим показателем, который дают обычные устройства GPS. На экваторе:
% gps distance "0.0, 179.0" "0.0, $((179 * (1 + 2**-23)))"
From 0.0, 179.0 to 0.0, 179.00002133846283 is 7.79 feet E
From 0.0, 179.0 to 0.0, 179.00002133846283 is 2.38 meters E
Таким образом, число с плавающей запятой одинарной точности IEEE 754, известное вашему компилятору C как float
, будет как раз подходящим для представления. Остерегайтесь использования чисел с плавающей запятой для расширенных вычислений! Ошибка округления может съесть ваш обед. Проконсультируйтесь с численным аналитиком.
РЕДАКТИРОВАТЬ: добавил несколько пунктов из комментариев, 32-битные значения должны обеспечивать достаточную точность.
Я бы использовал 32-битное представление с фиксированной точкой. Если значения:
42.915512
, -99.521654
, я бы сохранил значения * 100000
в int32_t
(они могут быть отрицательным).
int32_t lat = 42915512;
int32_t lon = -99521654;
Это хороший компромисс между простым и точным ( 5
десятичных знаков обычно достаточно, вы всегда можете увеличить его до 1000000
, чтобы получить 6
, если необходимо).
Чтобы отобразить пользователю, выполните то, что предлагает caf :
... чтобы отобразить пользователю - используйте целое число разделить и по модулю, например
printf ("Lat = % d.% 06d \ n ", lat / 1000000, abs (lat)% 1000000)
Их также можно будет эффективно сравнивать / сортировать, так как относительный порядок будет сохранен.
РЕДАКТИРОВАТЬ: Дополнительным преимуществом является то, что его можно отправлять по сети или сохранять на диск в двоичном формате. форматировать переносимым способом.
Я удивлен, что никто не опубликовал тот факт, что долгота / широта - ужасный способ хранения данных на сфере (кто-то упомянул, что долгота требует меньшей точности вблизи полюсов).
В основном вы можете сохранять данные о координатах X и Y в метрах. Представьте себе куб вокруг Земли, который точно соответствует (ха-ха, хорошо почти ему подходит). Вам нужно сохранить только координаты X и Y, а не все 3 координаты, потому что 3-я координата может быть получена из редиуса Земли, r = квадратный корень [x ^ 2 + y ^ 2 + z ^ 2] .
Итак, преобразуйте широту / долготу в x / y в метрах. Вам понадобится всего 12756200 м на координату (это диаметры земли). Таким образом, ваше общее значение должно быть только от 0 до 25 512 400 (кто-то еще заявил 40 000 000, потому что они использовали долгую / широту), чтобы быть точным с точностью до +/- 0,5 м.
Это даст всего 25 бит на позицию. На вашем месте я бы просто сделал точность в пределах 2 м и использовал 24 бита на позицию, так как это аккуратные 3 байта.
Также, если вы сохраняете информацию о путевых точках на пути, вы можете сохранять каждую путевую точку как смещение от последней путевой точки. Как начать с 24-битной координаты x / y. И затем есть 16-битное «обновление», которое регулирует положение, добавляя / вычитая метры x / y. 16-битный позволит обновить маршрутную точку на расстоянии более 400 метров. Так что, если вы знаете, что устройство не предназначено для самолетов и периодических обновлений, это тоже может быть приемлемо.
Как начать с 24-битной координаты x / y. А затем есть 16-битное «обновление», которое регулирует положение, добавляя / вычитая значения x / y. 16-битный позволит обновить маршрутную точку на расстоянии более 400 метров. Так что, если вы знаете, что устройство не предназначено для самолетов и периодических обновлений, это тоже может быть приемлемо. Как начать с 24-битной координаты x / y. И затем есть 16-битное «обновление», которое регулирует положение, добавляя / вычитая метры x / y. 16-битный позволит обновить маршрутную точку на расстоянии более 400 метров. Так что, если вы знаете, что устройство не предназначено для самолетов и периодических обновлений, это тоже может быть приемлемо.Вы можете упаковать значения широты и долготы в одно одно 32-битное целое число с разрешением худшее ~ 2,4 метра / пиксель (на экваторе), если вы используете рекурсивную систему листов. Используя два бита на уровень, вы можете сохранить 16 уровней в 32 бита. Вы можете получить представление о том, как это будет работать, просмотрев эту статью о тайловой системе виртуальной Земли . Здесь используется Меркатор, поэтому для полюсов возникнут проблемы. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.
Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).
4 метра / пиксель (на экваторе), если вы используете рекурсивную систему листов. Используя два бита на уровень, вы можете сохранить 16 уровней в 32 бита. Вы можете получить представление о том, как это будет работать, просмотрев эту статью о тайловой системе виртуальной Земли . Здесь используется Меркатор, поэтому для полюсов возникнут проблемы. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).
4 метра / пиксель (на экваторе), если вы используете рекурсивную систему листов. Используя два бита на уровень, вы можете сохранить 16 уровней в 32 бита. Вы можете получить представление о том, как это будет работать, просмотрев эту статью о тайловой системе виртуальной Земли . Здесь используется Меркатор, поэтому для полюсов возникнут проблемы. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).
так что это дало бы вам проблемы для полюсов. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).
так что это дало бы вам проблемы для полюсов. Вместо этого вы можете использовать другую проекцию и по-прежнему получать очень похожие результаты.Это также можно использовать для грубого фильтра , чтобы найти любые точки в заданном родительском тайле, поскольку первые N битов будут одинаковыми (и поэтому поиск становится битовым маскированием).
В формате карты Garmin IMG они хранят координаты внутри ограничивающих рамок, используя числа с плавающей запятой для установки краев прямоугольников. Координаты внутри полей определяются с использованием переменного числа битов, которые просто линейны между минимальным и максимальным значениями в зависимости от необходимой точности.
Например: minlat = 49.0, maxlat = 50.0, minlon = 122.0, maxlon = 123,0, количество бит = 16
Таким образом, значение:
32768 32768 будет преобразовано в 49,5, 122,5
16384,0 будет 49,25, 122,0
Если вам нужна меньшая точность, тот же результат может быть сгенерирован с количеством бит = 4
8,8 будет преобразовано в 49,5, 122,5
4,0 будет 49,25, 122,0