在Bitwise Operations中PHP的Infinit值返回奇怪的值

Y.H*_*mes 17 php bit-manipulation

今天我刚刚做了一个有趣的发现,同时测试了在php中按比例计算发生的事情INF ^ 0(^=> Bitwise Operator for Exclusive OR(XOR))是什么让我int(-9223372036854775808)在64位系统中得到了最大可能的负值.

但后来我问自己:"为什么当"正无限"意味着9223372036854775807(63位1有一个领先0)和0(64位0=> 0 xor 0 = 0)时XOR的结果为负,但PHP的无限值是什么,什么是它背后的计算?当我使用"负无限"时,为什么我得到一个(正确的?)负值(1一个领先0于0 => 1 xor 0 = 1?).

另一个有趣的观点是,这只发生在PHP版本5.5.9-1上,而不是发生在例如5.3.x上.和5.6.x(我已经测试过了)!也许有人知道那里会发生什么?在三个版本上测试它,但我的(5.5.9-1)给出了这些结果:

按位运算

只是为了让你们知道,这只是一个抽象的游戏,我为了好玩而做,但我发现它很有趣.也许有人可以在这帮助或解释我错误的想法?告诉我,如果有人需要更多关于任何事情的信息!

编辑:相应于jbafford,获得完整的答案会很棒,所以我只想引用他: why does 5.5 and 5.6 result in PHP_INT_MIN, and everything else return 0?

And*_*rea 7

首先,^本身并不是什么特别之处.如果你对零的异或,或者任何零的异或,你只需要回到原来的答案.你在这里看到的不是操作本身的一部分,而是操作之前发生的事情:按位运算符采用整数,因此PHP将浮点数转换为整数.它是浮点到整数转换中出现的奇怪行为,并且它不是按位运算符所独有的.(int)例如,它也会发生.

为什么会产生这些奇怪的结果呢?只是因为在将float转换为整数时,这就是编写PHP代码所产生的代码.在C标准中,C的浮点到整数转换的行为未定义为特殊值INF,-INF并且NAN(或者更确切地说,对于"整数部分",整数不能表示:§6.3.1.4).这种未定义的行为意味着编译器可以随意做任何事情.在这种情况下恰好发生它生成的代码在这里产生最小整数值,但不能保证总是会发生,并且它在整个平台或编译器中不一致.1为什么行为在5.4和5.5之间变化?因为用于将浮点数转换为整数的PHP代码更改为始终执行模数转换.这种固定的不确定的行为非常大的浮点数,2,但它仍然没有检查特殊值,所以这种情况下,它仍然产生不确定的行为,只是略有不同,这一次.

在PHP 7中,我决定使用Integer Semantics RFC清理PHP的这部分行为,这使得PHP检查特殊值(INF,-INFNAN)并一致地转换它们:它们总是转换为整数0.这里不再有未定义的行为.


1例如,我在C中编写的尝试将Infinity转换为整数(特别是C long)的测试程序在32位和64位构建上有不同的结果.64位构建总是产生-9223372036854775808最小整数值,而32位构建总是产生0.对于GCC和clang,这种行为是相同的,所以我猜他们都生成了非常相似的机器代码.

2如果您尝试将float转换为整数,并且该float的值太大而无法放入整数(例如PHP_INT_MAX * 2,或PHP_INT_MIN * 2),则结果未定义.PHP 5.5使结果保持一致,但不直观(如果将float转换为非常大的整数,则会起作用,并且丢弃最高有效位).