为什么 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 位数字的值会被解析,以防它们在范围内,但使用的逻辑不是为超出范围的值设计的,也不打算与超出范围的值保持一致。
如果我在 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 位数字的值会被解析,以防它们在范围内,但使用的逻辑不是为超出范围的值设计的,也不打算与超出范围的值保持一致。