为什么 PHP 中没有整数 "underflow"?

Why don't integers "underflow" in PHP?

如果我在 PHP 中这样做:

echo (int)9223372036854775808;

输出是-9223372036854775808,这是完美的,因为二进制的9223372036854775807是:

0111 ... 1

即 0 后跟 63 个。显然二进制中的 1 只是 1,所以当我添加它们时我得到 1000...0(1 后面有 63 个 0)这是 -9223372036854775808 的 2s 补码符号。

所以我希望如果我对 -9223372036854775808 添加 -1,我会得到 9223372036854775807。4 位二进制的类比如下:

1000   (-8)
1111   (-1)
----
0111   (7)

我知道我不能简单地将 -9223372036854775809 分配给一个变量,因为没有 64 位有符号整数表示,但为什么这不起作用:

$smallest_int = (int)-9223372036854775808;

echo (int)($smallest_int-1); //similar to 1000+1111 in 4 bit

当我运行这个输出仍然是-9223372036854775808。为什么会这样?这与 PHP 的弱类型有关吗?这会发生在其他语言中吗(我知道它肯定不会发生在 C 中)?

我在这里猜测,因为没有键入数字,PHP 实际上是将您的数字转换为浮点数,然后 -1 在数学中丢失了。

9223372036854775808变成-9223372036854775808是对的,但不是"integers wrap around"那么简单。这里还有一些映射(通过实验发现):

  • 9223372036854775809→仍然是-9223372036854775808(不是-9223372036854775807
  • 9223372036854775810→仍然是-9223372036854775808(不是-9223372036854775806

所以您可能认为 int 范围外的数字都映射到 -9223372036854775808 — 但是等等! :

  • 9323372036854775810 → -9123372036854775808
  • 92233720368547758080 → 0

所有这些对我来说似乎都很武断。我认为正在发生的事情是,长度超过 18 位数字(因此很容易被识别为超出整数范围)的值基本上被丢弃并替换为零,而长度为 18 位数字的值会被解析,以防它们在范围内,但使用的逻辑不是为超出范围的值设计的,也不打算与超出范围的值保持一致。