java 中的溢出如何工作?

How does overflow work in java?

我读过有关溢出的内容,我知道 "Overflow is when a number is so large that it will no longer fit within the data type, so the system “wraps around” to the next lowest value and counts up from there"。

例如:

short s = (short)1921222; // Stored as 20678

在那个例子中,我们从 -32768 (Short.MIN_VALUE) 开始计数,但是当我尝试用另一种整数数据类型证明时,它似乎工作不一样方式...

byte b = (byte)400; // Stored as -112

上面的例子从 0 开始计数,这是我发现得到 -112

的唯一方法

不知道是不是我做错了

演员正在截断号码。 (JLS)

0000 0001 1001 0000

丢高字节变成

1001 0000

也就是-112。

在 java 中,byte 基本类型是一个 8 bit 有符号 整数,这就是为什么你从调用中得到 -112 :

byte b = (byte) 400;

你可以避免这种情况并获得它的无符号值,通过二进制将它与 0xFF 相加,如下所示:

int b = (byte) 400 & 0xFF;

更多详情您可以查看:

Java Language Specification 说:

The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers, respectively, and char, whose values are 16-bit unsigned integers representing UTF-16 code units.

因此,shortbyte 都是 two's complement 整数。

short 是 16 位,这意味着它可以容纳 2^16 = 65536 个不同的值。在第65536个值后溢出。
1921222 模 65536 是 20678。这小于 32768(2^15,二进制补码的转折点)所以我们保留一个正数。

byte 是 8 位,这意味着它可以容纳 2^8 = 256 个不同的值。这个在第 256h 个值之后溢出。 400 模 256 为 144。此值高于 128,即二进制补码的转折点 - 因此它将被解释为负二进制补码数。

除了其他答案,您也可以通过手动计算得出该答案。

在Java中,数据类型byte是一个8位有符号整数。所以这些值在 [-128, 127] 区间内。如果您有一个 400 的值,并且您想要查看该类型的实际值,您可以从该数字中减去间隔的 size,直到您得到一个值在区间内。

前面说过,byte是8位,所以区间的大小是256。从您的初始值中减去:400 - 256 = 144。该值仍然在间隔之外,因此您必须再次减去:144 - 256 = -112。该值现在位于区间内,确实是您在测试中看到的值。

您的第一个示例也是如此:short 是 16 位且有符号,因此间隔为 [-32768, 32767],大小为 65536。从值 1921222 中重复减去最终会得到您在测试中看到的值 20678