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

这只发生在负数..

更新地址。信息:

  • 一个 var 转储给出þØçï_Kstring(25) "þØçï_K"
  • bin2hex 给出000e1b00000000fe1a16d806e707ef0000045f0000004b0000

将函数简化为仅包含数字输入,输出仍然不同

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

4263.12265在 MAMP 和-31.84465LAMP 上

4

1 回答 1

4

这是一个 32 位与 64 位的问题。

因为您的最高有效字节大于 127,所以在 32 位平台上,由于整数溢出,这被解释为负值 - 最高有效位已设置。在 64 位平台上不是这样。

解决方案是使用pack()unpack()因此您可以指定应该对整数进行签名。编辑 修复了这个代码示例见编辑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 回答