溢出如何在java中工作?

时间:2017-11-28 14:13:10

标签: java integer-overflow

我已经读过有关溢出的内容,我知道“溢出是指一个数字如此之大以至于它将不再适合数据类型,因此系统”回绕“到下一个最低值并从那里开始计数”

例如:

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

在那个例子中,我们从 -32768 (Short.MIN_VALUE)开始计算,但是当我尝试在另一个整数数据类型中进行证明时,它似乎没有相同的方式... < / p>

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

以上示例从 0 开始计算,这是我找到的唯一方法 -112

我不知道我做错了什么。

4 个答案:

答案 0 :(得分:17)

Java Language Specification说:

  

整数类型是byte,short,int和long,其值分别是8位,16位,32位和64位二进制补码整数,以及char,其值为16-表示UTF-16代码单元的位无符号整数。

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

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

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

答案 1 :(得分:16)

演员正在截断数字。 (JLS

0000 0001 1001 0000

丢失高字节成为

1001 0000

是-112。

答案 2 :(得分:6)

在java中,byte基元类型是8 bit 签名整数,这就是您调用-112的原因:

byte b = (byte) 400;

您可以避免这种情况,并通过二进制文件将其添加到0xFF来获取其未签名的值:

int b = (byte) 400 & 0xFF;

有关详细信息,请查看:

答案 3 :(得分:3)

除了其他答案,你也可以通过人工计算得到答案。

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

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

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