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 Primitive data types 文档。
- How to Convert Int to Unsigned Byte and Back
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.
因此,short
和 byte
都是 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
。
我读过有关溢出的内容,我知道 "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 Primitive data types 文档。
- How to Convert Int to Unsigned Byte and Back
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.
因此,short
和 byte
都是 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
。