在PHP中否定十六进制,有趣的行为

时间:2012-03-08 20:02:20

标签: php hex negate

有一些奇怪的行为我想知道是否有人可以为我清理。

检查出来

$hex = 0x80008000;

print_r(decbin(intval($hex)) . '<br/>');
print_r(decbin($hex));

输出

10000000000000001000000000000000
10000000000000001000000000000000

正如所料。

但是

$hex = 0x80008000;

print_r(decbin(~intval($hex)) . '<br/>');
print_r(decbin(~$hex));

输出

1111111111111110111111111111111
1111111111111111111111111111111

为什么在$hex被否定时中间位不会切换?

2 个答案:

答案 0 :(得分:0)

在这里给出我自己的问题。

是的,这是一个32位/ 64位的差异。

在32位系统中,float类型必须占用两个内存空间才能获得所需的64位。 Php使用双精度(见http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers

$ hex计算为float类型。 Intval和decbin函数将其转换为int类型(上面的第一个示例)

在第二个例子中,我们在使用decbin之前使用非按位运算符。这将首先翻转双内存空间双精度浮点中的位,然后转换为int秒。给我们一些不同于我们预期的东西。

实际上,如果我们将intval()中的否定置于其中:

$hex = 0x80008000;

print_r(decbin(intval(~$hex)) . '<br/>');
print_r(decbin(~$hex));

我们得到了

1111111111111111111111111111111
1111111111111111111111111111111

作为输出。

我还不够用数学来证明这一点(可以在本文http://en.wikipedia.org/wiki/Double_precision的帮助下弄清楚)。但也许我以后有时间-_-

我认为了解如何在计算机中表示数字非常重要,这样我们就可以理解这样的异常,而不是将它们称为错误。

答案 1 :(得分:-1)

可能属于这个案例:

从php按位运算符页面http://us3.php.net/manual/en/language.operators.bitwise.php

  

NOT或补码运算符(〜)和负二进制数可以   令人困惑。

     

~2 = -3因为你使用公式~x = -x - 1按位   十进制数的补码是数字减1的否定。

     

注意:这里仅使用4位用于下面的示例,但实际上是PHP   使用32位。

     

将负十进制数(即:-3)转换为二进制数需要3   步骤:1)将十进制数的正数转换为   二进制(即:3 = 0011)2)翻转位(即:0011变为1100)3)加   1(即:1100 + 0001 = 1101)

     

你可能想知道1101 = -3是怎么回事。 PHP使用该方法   “2的补码”来呈现负二进制数。如果最左边   bit是1然后二进制数是负数,你翻转位   并添加1.如果为0则为正,您不必这样做   任何东西。因此,0010将是积极的2.如果是1101,则为负   然后翻转位以获得0010.添加1并获得等于的0011   -3。