我知道从度数转换为毫秒的公式,反之亦然。它可以这样实现:
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)
还有另一种减少差异的方法是由度数和毫秒之间的转换引起的吗?
答案 0 :(得分:3)
有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函数fmod
或modf
等效的内容。
如果有双重精确的方法,你可以再一次完成所有操作:
$decimaldegrees = ((double)($millis)) / (60*60*1000);
如果您无法获得双精度,则无法安全地重构,单精度没有足够的位......
您需要在单独的字符串部分上操作,在分数部分
中处理前导零无论如何,我强烈建议你进行单元测试,即分别测试你的两个功能,这样你就可以更好地理解什么有效,什么无效。