1

I know the formular for conversion from Degree to Milliseconds and vice-versa. It can be implemented like that:

 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;
    }

Scenario: I convert from Degree to Miliseconds and continue converting from Miliseconds to Degree. The converted value has some difference with original value. I want the value is exact as the orginal value as well. For example:

$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)

Is there another way to reduce difference is caused by conversion between degree and milliseconds?

4

1 回答 1

3

有360度(经度),每度60分,每分钟60秒,每秒1000毫秒。所以最多

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

这非常适合 31 位,因此想法是首先转换为整数,并以整数执行尽可能多的操作。

请注意,如果您使用单精度浮点,您将获得 24 位有效位,并且会在十分之一秒(log2(360*60*60*10)大约1 秒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,大概是因为某些算术运算是用整数算术执行的,因此会丢弃毫秒。

$s = $s % 3600;再一次,我不太了解 php,但实际上不会操作(int)(%s)并因此丢弃毫秒?
您需要找到与 C 函数fmodmodf.

再一次,如果有办法以双精度执行所有操作,您可以一次执行所有操作:

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

如果您无法访问双精度,则无法安全地重新组合,单精度没有足够的位......

您需要对单独的字符串部分进行操作,注意小数部分中的前导零

无论如何,我强烈建议执行单元测试,即分别测试您的两个功能,这样您将更好地了解哪些有效,哪些无效。

于 2013-06-26T13:54:57.657 回答