PHP和Apache2中的奇怪行为:不同服务器中的不同输出

时间:2012-12-31 08:45:04

标签: php apache mamp lamp

我在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;
MAMP上的

4263.12265和LAMP上的-31.84465

1 个答案:

答案 0 :(得分:4)

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

因为你最重要的字节是&gt; 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;