Преобразование между степенью и Miliseconds

Я знаю формуляр для преобразования от степени к Miliseconds и наоборот. Он может быть реализован следующим образом:

protected function decimal_to_milisecond($dec) { if (!empty($dec)) { $vars = explode(".",$dec); if (count($vars) == 2) { $deg = $vars[0]; $tempma = "0.".$vars[1]; $tempma = $tempma * 3600; $min = floor($tempma / 60); $sec = $tempma - ($min*60); return round((((($deg * 60) + $min) * 60 + $sec) * 1000)); } else return false; } else return false; } function milisecond_to_decimal($sec) { if (!empty($sec)) { $s = $sec / 1000; $d = (int)($s / 3600); $s = $s % 3600; $m = (int)($s / 60); $s %= 60; $ret = substr($d+((($m*60)+($s))/3600),0); } else return null; return $ret; } 

Сценарий: я конвертирую из Degree в Miliseconds и продолжаю конвертировать из Miliseconds в Degree. Преобразованное значение имеет некоторую разницу с исходным значением. Я хочу, чтобы значение было точным, как оригинальное значение. Например:

 $lat = "1284146"; $long = "503136198"; $lat1 = milisecond_to_decimal($lat); $long1 = milisecond_to_decimal($long); $result1 = decimal_to_milisecond($lat1); $result2 = decimal_to_milisecond($long1); var_dump($result1, $result2); The output is float(1284000) and float(503136000) 

Есть ли другой способ уменьшить разницу, вызванный конверсией между степенью и милисекундами? Спасибо.

Есть 360 градусов (долгота), 60 минут на градус, 60 секунд в минуту, 1000 миллисекунд в секунду. Так что самое большее

 360*60*60*1000 milliseconds = 1 296 000 000 milliseconds 

Это хорошо подходит для 31 бит, поэтому идея состояла бы в том, чтобы сначала преобразовать в целое число и выполнить как можно больше операций в целых числах.

Обратите внимание: если вы используете одинаковую точность с плавающей запятой, вы получите значение в 24 бита и потеряете точность до 1 десятой секунды ( log2(360*60*60*10) составляет около 23.6 ).

Я бы рекомендовал хранить результаты с двойной точностью (53 бит).

РЕДАКТИРОВАТЬ

То, что я предлагаю, – это выполнить преобразование сразу, если есть способ использовать двойную точность для представления $decimaldegrees (я не знаю, php достаточно, чтобы сказать это), что-то вроде:

 $millis = (int)( round( $decimaldegrees * (60*60*1000) ) ); 

Затем, если вы хотите разложить на DMS (но эти переменные не используются в вашем коде):

 $ms = $millis % 1000; $sec = ($millis / 1000) % 60; $min = ($millis / (60*1000)) % 60; $deg = ($millis / (60*60*1000)) % 360; 

Более глубокий взгляд на ваш код, кажется, вы отделяете десятичную часть сначала $tempma = "0.".$vars[1];
Это может работать, если вы работаете с строкой десятичного представления, потому что в этом случае это хорошо подходит даже для одного прецизионного поплавка ( log2(60*60*1000) составляет около 21.8 ). Таким образом, начало можно заменить:

 $deg = (int) $vars[0]; $frac = "0.".$vars[1]; $millis = (int)( round( $frac * (60*60*1000) ) ); $millis = deg + millis; 

Из примера вывода, который вы дали, похоже, что проблема исходит из другого преобразования milisecond_to_decimal , предположительно потому, что некоторая арифметическая операция выполняется с целочисленной арифметикой и, таким образом, отбрасывает миллисекунды.

Еще раз, я не знаю php достаточно, но не $s = $s % 3600; фактически действуют на (int)(%s) и, таким образом, отбрасывают миллисекунды?
Вам нужно будет найти что-то эквивалентное функции C modf или modf .

Еще раз, вы можете сделать все операции сразу, если есть способ сделать это с двойной точностью:

 $decimaldegrees = ((double)($millis)) / (60*60*1000); 

Если у вас нет доступа к двойной точности, вы не можете перекомпоновать безопасно, у одной точности не хватает бит …

Вам нужно будет работать на отдельных частях струны, заботясь о ведущих нулях во фракционной части

Во всяком случае, я настоятельно рекомендую выполнить модульные тесты, то есть проверить ваши две функции отдельно, таким образом вы сможете лучше понять, что работает, а что нет.