按位操作中的PHP Infinit值返回奇怪的值怎么处理?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (24)

今天,我在测试php中如何计算比特INF ^ 0^=>按位异或(XOR)的位运算符)时发现了一个有趣的发现,它给了我int(-9223372036854775808)在64位系统中最大的负值。

但后来我问自己:“为什么当”正向无限“意味着92233720368547758071带领先的63位0)和0(64位开启0=> 0 xor 0 = 0)时,XOR的结果为负数。尽管PHP的infinit值是什么,但是什么是在它后面的计算?当我使用“负无穷大”(一个领先的0 => ?1领先)时,为什么我会得到一个(正确的?)负值。01 xor 0 = 1

另一个有趣的地方是,这只发生在PHP版本5.5.9-1上,而不是在5.3.x上发生。和5.6.x(我已经测试过了)!也许有人有一个想法发生了什么?测试了三个版本,但只是我的(5.5.9-1)给出了这些结果:

只是为了让大家知道,这只是我为乐趣而做的抽象游戏,但我觉得它很有趣。也许有人可以在这里帮助或向我解释我有一个错误的想法?告诉我,如果有人需要更多关于任何事情的信息!

提问于
用户回答回答于

首先,^本身并不是什么特别的东西。如果你用零来异或任何零的东西,你只要回到原来的答案。这里看到的不是操作本身的一部分,而是操作之前发生的事情:位运算符采用整数,所以PHP将float转换为整数。浮点到整数的转换出现了奇怪的行为,它不是排他性的按位运算符。(int)例如,它也会发生。

为什么会产生这些奇怪的结果?仅仅因为这就是将float转换为整数时生成的C代码写入的内容。在C标准,C的浮法到整数转换行为是未定义为的特殊值INF-INFNAN(或,更准确地,对于“组成部分”的整数不能代表:§6.3.1.4)。这个未定义的行为意味着编译器可以自由地执行任何想要的操作。在这种情况下恰好如此,它生成的代码在此处生成最小整数值,但不能保证总会发生,并且在平台或编译器中不一致。1为什么行为在5.4和5.5之间变化?因为PHP将浮点数转换为整数的代码更改为始终执行模数转换。这固定了非常大的浮点数的未定义行为2,但它仍然没有检查特殊值,所以在这种情况下,它仍然产生未定义的行为,这次略有不同。

在PHP 7,我决定要清理的PHP与行为这部分整数语义RFC,这使得PHP检查的特殊值(INF-INFNAN一致),并将其转换:他们总是转换为整数0。在这里工作不再有未定义的行为。

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

2如果你尝试将float转换为整数,并且该float值太大而不适合整数(例如PHP_INT_MAX * 2PHP_INT_MIN * 2),则结果未定义。PHP5.5使得结果一致,尽管不直观(如果float被转换为一个非常大的整数,并且最高有效位被丢弃,它就会起作用)。

用户回答回答于

float(INF)隐式转换为一个Integer。

并且与0异或不会改变第一个参数。所以基本上这只是从float到int的转换,对于不在整数范围内的值未定义。(对于所有其他值,它将被截断为零)

扫码关注云+社区