Convert between Degree and Milliseconds(在度数和毫秒之间转换)
问题描述
我知道从度到毫秒的转换公式,反之亦然.可以这样实现:
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?
推荐答案
有360度(经度),每度60分,每分钟60秒,每秒1000毫秒.所以最多
There are 360 degrees (longitude), 60 minutes per degree, 60 secondes per minute, 1000 milliseconds per second. So at most
360*60*60*1000 milliseconds = 1 296 000 000 milliseconds
这很适合 31 位,因此我们的想法是首先转换为整数,并以整数执行尽可能多的操作.
That fits well on 31 bits, so the idea would be to first convert to an integer, and perform as much operations as possible in integer.
请注意,如果您使用单精度浮点数,您将获得 24 位有效位,并且会在十分之一秒内失去精度(log2(360*60*60*10)
约为23.6
).
Note that if you use single precision floating point, you'll get a 24 bits significand and will loose accuracy under 1 tenth of second (log2(360*60*60*10)
is about 23.6
).
我建议以双精度(53 位有效位)存储结果.
I would recommend to store results in double precision (53 bits significand).
编辑
我的建议是一次执行转换,如果有一种方法可以使用双精度来表示 $decimaldegrees
(我对 php 的了解不足以说明这一点),一些喜欢:
What I was suggesting is to perform the conversion all at once, if there is a way to use double precision for representing $decimaldegrees
(I don't know php enough to tell so), something like:
$millis = (int)( round( $decimaldegrees * (60*60*1000) ) );
那么如果你想分解成 DMS(但这些变量没有在你的代码中使用):
Then if ever you want to decompose into DMS (but these variables are not used in your code):
$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
).所以开头可以替换为:
Ater a deeper look at you code, it seems you are separating the decimal part first $tempma = "0.".$vars[1];
That could work if you work on the decimal representation string, because in this case that fits well even on a single precision float (log2(60*60*1000)
is about 21.8
). So the beginning could be replaced with:
$deg = (int) $vars[0];
$frac = "0.".$vars[1];
$millis = (int)( round( $frac * (60*60*1000) ) );
$millis = deg + millis;
从您给出的输出示例中,听起来问题来自其他转换milisecond_to_decimal
,大概是因为某些算术运算是使用整数算术执行的,因此会丢弃毫秒.
From the example of output you gave, it sounds like the problem comes from the other conversion milisecond_to_decimal
, presumably because some arithmetic operation is performed with integer arithmetic and thus discards the milliseconds.
再一次,我对php不够了解,但不会 $s = $s % 3600;
实际上对 (int)(%s)
从而丢弃毫秒?
您需要找到与 C 函数 fmod
或 modf
等价的东西.
Once again, I don't know php enough, but wouldn't $s = $s % 3600;
in fact operate on (int)(%s)
and thus discard the milliseconds?
You would need to find something equivalent to C function fmod
or modf
.
再一次,如果有办法以双精度执行所有操作,您可以一次执行所有操作:
Once again, you could do all operation at once if there is a way to do it in double precision:
$decimaldegrees = ((double)($millis)) / (60*60*1000);
如果您无法访问双精度,则无法安全地重构,单精度没有足够的位...
If you don't have access to double precision, you can't recompose safely, single precision does not have enough bits...
您需要对单独的字符串部分进行操作,注意小数部分中的前导零
You would need to operate on separate string parts, caring of leading zeros in fraction part
无论如何,我强烈建议进行单元测试,即分别测试你的两个函数,这样你就可以更好地了解什么有效,什么无效.
Anyway, I strongly suggest to perform unit tests, that is to test your two functions separately, this way you'll get a better understanding of what works and what not.
这篇关于在度数和毫秒之间转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在度数和毫秒之间转换
基础教程推荐
- XAMPP 服务器不加载 CSS 文件 2022-01-01
- WooCommerce 中选定产品类别的自定义产品价格后缀 2021-01-01
- 在 Woocommerce 中根据运输方式和付款方式添加费用 2021-01-01
- 通过 PHP SoapClient 请求发送原始 XML 2021-01-01
- 在 PHP 中强制下载文件 - 在 Joomla 框架内 2022-01-01
- Libpuzzle 索引数百万张图片? 2022-01-01
- 超薄框架REST服务两次获得输出 2022-01-01
- 如何在 PHP 中的请求之间持久化对象 2022-01-01
- 在多维数组中查找最大值 2021-01-01
- mysqli_insert_id 是否有可能在高流量应用程序中返回 2021-01-01