我已经阅读了有关溢出的信息,我知道"溢出是当一个数字如此之大以至于它不再适合数据类型,因此系统"绕开"到下一个最低值,从那里计数"。
例如:
short s = (short)1921222; // Stored as 20678
在那个示例中,我们开始从 -32768 (Short.MIN_VALUE)
进行计数,但是当我尝试在其他整数数据类型中证明时,它似乎并没有以相同的方式工作...
byte b = (byte)400; // Stored as -112
上面的示例从 0 开始计数,这是我发现获得 -112
的唯一方法我不知道我是否做错了什么。
Java语言规范说:
积分类型分别为8位,16位,32位和64位的字节,短,int和长,分别签署了两个符合整数,其值为16--代表UTF-16代码单元的位无符号整数。
所以, short
和 byte
都是两个的补充整数。
short
是16位,这意味着它可以保持2^16 = 65536不同的值。在第65536个值之后,它溢出。
1921222 Modulo 65536是20678。这小于32768(2^15,两者补充的转折点),因此我们保持一个正数。
byte
是8位,这意味着它可以保持2^8 = 256个不同的值。这个值在256小时之后溢出。400 Modulo 256是144。该值高于128,这是两者补充的转折点 - 因此将被解释为负两个的补体编号。
铸件正在截断数字。(JLS)
0000 0001 1001 0000
失去高字节
1001 0000
是-112。
在Java中,byte
原始类型是8 bit
签名 Integer,这就是为什么您从呼叫中获得-112
的原因:
byte b = (byte) 400;
您可以通过将其添加到0xFF
这样的二进制文件来避免并获得其未签名的值:
int b = (byte) 400 & 0xFF;
有关更多详细信息,您可以检查:
- Java 原始数据类型文档。
- 如何将int转换为未签名的字节和back
除了其他答案之外,您还可以通过手动计算获得该答案。
在Java中,数据类型byte
是一个8位,已签名整数。因此值是在间隔[-128, 127]
中。如果您的值为400
并且想查看该类型的实际值,则可以从该数字中减去间隔的 size ,直到您达到间隔内的值。
正如我所说,byte
是8位,因此间隔的大小为256
。从您的初始值中减去:400 - 256 = 144
。此值仍然不在间隔之外,因此您必须再次减去:144 - 256 = -112
。该值现在在间隔内,确实是您在测试中看到的值。
对于您的第一个示例也是如此:short
是16位并签名,因此间隔为[-32768, 32767]
,尺寸为65536
。从值1921222
进行重复减法最终将为您提供测试中所见的值20678
。