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)

度とミリ秒の間の変換によって引き起こされる違いを減らす別の方法はありますか?

4

1 に答える 1

3

360 度 (経度)、1 度あたり 60 分、1 分あたり 60 秒、1 秒あたり 1000 ミリ秒があります。だからせいぜい

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

これは 31 ビットにうまく適合するため、最初に整数に変換し、整数で可能な限り多くの操作を実行するという考え方になります。

単精度浮動小数点を使用すると、仮数が 24 ビットになり、精度が 10 分の 1 秒 (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);

倍精度にアクセスできない場合、安全に再構成できません。単精度では十分なビットがありません...

分数部分の先行ゼロを考慮して、別々の文字列部分を操作する必要があります

とにかく、単体テストを実行することを強くお勧めします。つまり、2 つの機能を別々にテストすることです。これにより、何が機能し、何が機能しないかをよりよく理解できます。

于 2013-06-26T13:54:57.657 に答える