【问题标题】:Convert between Degree and Milliseconds在度数和毫秒之间转换
【发布时间】:2019-03-12 11:33:18
【问题描述】:

我知道从度到毫秒的转换公式,反之亦然。可以这样实现:

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

场景:我将度数转换为毫秒,并继续从毫秒转换为度数。转换后的值与原始值有一定的差异。我希望该值也与原始值完全相同。例如:

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

有没有另一种方法来减少度数和毫秒之间的转换造成的差异?

【问题讨论】:

  • 根据代码,表示度-分-秒。
  • @DevZer0:抱歉我更新了。
  • 嗯?区别” ?您正在使用round(),这意味着它将对您的输出进行四舍五入,从而产生“差异”。
  • @HamZa:我使用 round() 所以差异将小于或等于 0.5 毫秒。但我想将它减小到比 round() 更小。
  • @secretlm 不知道你想要什么,但是round() 有第二个参数precision,看看吧。

标签: php floating-point geolocation rounding precision


【解决方案1】:

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

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

这很适合 31 位,因此我们的想法是首先转换为整数,然后以整数执行尽可能多的操作。

请注意,如果您使用单精度浮点,您将获得 24 位有效位,并且精度会降低到十分之一秒以下(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 函数 fmodmodf 等效的内容。

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

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

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

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

无论如何,我强烈建议进行单元测试,即分别测试你的两个函数,这样你就可以更好地了解什么有效,什么无效。

【讨论】:

  • 感谢您的回答。但是,我并不清楚您的想法。你能详细解释一下吗?谢谢。
  • 非常感谢您的解释!
猜你喜欢
  • 2014-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 2013-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多