我在Mac和Linux上运行的PHP代码中遇到不同的输出。
我有两台服务器运行以下代码:
$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
(不正确)。
在LAMP栈(Ubuntu)运行相同的PHP版本,它会返回确切的负值-31.84465
。
这只发生在负数
更新Addl。 信息:
þØçï_Kstring(25) "þØçï_K"
000e1b00000000fe1a16d806e707ef0000045f0000004b0000
简化function只包括数字input,输出仍然不同 :
$ltt = (254 << 24 | 26 << 16 | 22 << 8 | 216)/ 1000000;
MAMP上的-31.84465
和LAMP上的-31.84465
这是一个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;