PHP位运算中的 Infinit 值 returns 奇怪的值

PHP's Infinit value in Bitwise Operations returns strange values

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

但后来我问自己:"Why is the result going negative in XOR when the "positive infinit" 表示 92233720368547758071 上的 63 位,前导 0)和 0(0 上的 64 位0 => 0 xor 0 = 0) PHP 的无限值是多少,它背后的计算是什么?为什么我在使用 [= 时得到(正确的?)负值38=](0 => 1 xor 0 = 1 上的前导 1 与前导 0 的对比?

另一个有趣的点是,这只发生在 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?

您的 float(INF) 被隐式转换为整数。

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

https://3v4l.org/52bA5

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

为什么会产生这些奇怪的结果?仅仅是因为在将浮点数转换为整数时,C 代码 PHP 就是这样写的。在 C 标准中,对于 INF-INFNAN(或,更准确地说,对于 "integral parts" 一个整数不能表示:§6.3.1.4). This undefined behaviour means the compiler is free to do whatever it wants. It just so happens in this case that the code it generates produces the minimum integer value here, but there's no guarantee that will always happen, and it's not consistent across platforms or compilers.1 Why did the behaviour change between 5.4 and 5.5? Because PHP's code for converting floats to integers changed to always perform a modulo conversion。这修复了非常大的浮点数的未定义行为,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 如果您尝试将浮点数转换为整数,并且该浮点数的值太大而无法放入整数(例如 PHP_INT_MAX * 2,或 PHP_INT_MIN * 2),结果未定义。 PHP 5.5 使结果一致,但不直观(如果浮点数被转换为一个非常大的整数,并且最高有效位被丢弃,它就会起作用)。