0

MacとLinuxで実行されているPHPコードで異なる出力が発生しています。

次のコードを実行している2台のサーバーがあります。

    $ltt = ((ord($str[7]) << 24) | (ord($str[8]) << 16) | (ord($str[9]) << 8) | (ord($str[10]))) / 1000000;

出力もord(str[ ])同じです:

[7] = 254
[8] = 26
[9] = 22 
[10] = 216

ただし、php 5.3.6を実行しているMAMPスタック(Mac)では、$ lttが元々負の数であると想定されている場合、4263.12265(正しくない)戻ります。

同じphpバージョンを実行しているLAMPスタック(Ubuntu)では、正確な負の値が返されます-31.84465

これは負の数でのみ発生します。

Addlを更新します。情報:

  • varダンプはþØçï_Kstring(25) "þØçï_K"
  • bin2hexは与える000e1b00000000fe1a16d806e707ef0000045f0000004b0000

数値入力のみを含むように関数を単純化しても、出力は異なります

$ltt = (254 << 24 | 26 << 16 |  22 << 8 | 216)/ 1000000;

4263.12265MAMPと-31.84465LAMPで

4

1 に答える 1

4

これは 32 対 64 ビットの問題です。

最上位バイトが > 127 であるため、32 ビット プラットフォームでは、整数オーバーフローのために負の値として解釈されます。最上位ビットが設定されます。64 ビット プラットフォームではそうではありません。

解決策は使用することでpack()ありunpack()、整数に署名する必要があることを指定できます。EDIT このコードサンプルを修正しましたedit 2 を参照してください

$packed = pack('C*', ord($str[7]), ord($str[8]), ord($str[9]), ord($str[10]));
$unpacked = unpack('l', $packed);
$lat = current($unpacked);

...ただし、これはリトル エンディアン アーキテクチャでは機能しないことに注意してください。これは、バイト順が間違っているためです。これを回避するには、パックされたバイトの順序を逆にするだけです。

編集2

わかりました、これについて理解するのにしばらく時間がかかりましたが、最終的にはそこにたどり着きました:

あなたがする必要があるのは、最上位ビットが設定されている場合、または最下位32ビットが設定されていないが残りが設定されている数値を持つ結果です。したがって、以下は 32 ビットと 64 ビットの両方で機能します。

<?php

// The input bytes as ints
$bytes = array(254, 26, 22, 216);

// The operand to OR with at the end
$op = $bytes[0] & 0x80 ? (~0 << 16) << 16 : 0;

// Do the bitwise thang
$lat = (($bytes[0] << 24) | ($bytes[1] << 16) | ($bytes[2] << 8) | $bytes[3]) | $op;

// Convert to float for latitude
$lat /= 1000000;

echo $lat;
于 2012-12-31T09:25:23.663 に答える