1

我知道度數轉換爲毫秒的公式,反之亦然。它可以這樣實現:度和毫秒之間的轉換

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) 

是否有另一種方法來減少差異是由度和毫秒之間的轉換引起的?非常感謝。

+0

什麼是DMS? – DevZer0

+0

根據代碼,它表示度分秒。 –

+0

@ DevZer0:對不起,我更新了。 – secretlm

回答

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函數fmodmodf的東西。

再次

,你可以做所有的操作一次,如果有一種方法可以做到這一點在雙精度:

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

如果你沒有獲得雙精度,你不能安全地重構,單精度沒有足夠的位......

您需要在不同的串件工作,在小數部分的前導零的關懷

不管怎麼說,我強烈建議執行單元測試,即測試你的兩個函數分開,這樣y你會更好地理解什麼有效,什麼不可行。

+0

感謝您的回答。但是,我不明白你的想法。你能解釋更多的細節嗎?謝謝。 – secretlm

+0

非常感謝您的解答! – secretlm