简体   繁体   English

溢出如何在java中工作?

[英]How does overflow work in java?

I've read about overflow, I know that "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". 我已经读过有关溢出的内容,我知道“溢出是指当一个数字如此之大以至于它将不再适合数据类型时,所以系统”回绕“到下一个最低值并从那里开始计数”。

For example: 例如:

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

In that example we started counting from -32768 (Short.MIN_VALUE) , but when I try to prove in another integer data types, it doesn't seem work the same way... 在那个例子中,我们从-32768 (Short.MIN_VALUE)开始计数,但是当我尝试在另一个整数数据类型中进行证明时,它似乎没有相同的工作方式......

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

The example above started counting from 0 that was the only way I found to get -112 上面的例子从0开始计数,这是我发现得到-112的唯一方法

I don't know if I am doing something wrong. 我不知道我做错了什么。

The Java Language Specification says: Java语言规范说:

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. 整数类型是byte,short,int和long,其值分别为8位,16位,32位和64位二进制补码整数,以及char,其值为16位无符号整数代表UTF-16代码单元。

So, short and byte are both two's complement integers. 因此, shortbyte都是两个补码整数。

short is 16 bits, meaning it can hold 2^16 = 65536 different values. short是16位,这意味着它可以容纳2 ^ 16 = 65536个不同的值。 After the 65536th value, it overflows. 在65536th值之后,它溢出。
1921222 modulo 65536 is 20678 . 1921222 modulo 65536是20678。 This is less than 32768 (2^15, the turning point for the two's complement) so we keep a positive number. 这小于32768(2 ^ 15,两个补码的转折点)所以我们保持正数。

byte is 8 bits, meaning it can hold 2^8 = 256 different values. byte是8位,这意味着它可以容纳2 ^ 8 = 256个不同的值。 This one overflows after the 256hth value. 这个值在第256个值之后溢出。 400 modulo 256 is 144. This value is higher than 128, the turning point for the two's complement - hence it will be interpreted as a negative two's complement number. 400模256为144.该值高于128,即两个补码的转折点 - 因此它将被解释为负2的补数。

The cast is truncating the number. 演员正在截断数字。 ( JLS ) JLS

0000 0001 1001 0000

loses the high byte to become 失去高字节成为

1001 0000

which is -112. 这是-112。

In java, byte primitive type is an 8 bit signed integer, that's why you got -112 from calling: 在java中, byte基元类型是一个8 bit 符号整数,这就是你调用-112的原因:

byte b = (byte) 400;

You can avoid that and get its un-signed value, by binary adding it with 0xFF like this: 您可以避免这种情况并获得其未签名的值,通过二进制将其添加为0xFF如下所示:

int b = (byte) 400 & 0xFF;

For further details you can check: 有关详细信息,请查看:

In addition to the other answers, you can get to that answer by manual calculation as well. 除了其他答案,您还可以通过手动计算得到答案。

In Java, the data type byte is an 8-bit, signed integer. 在Java中,数据类型byte是一个8位有符号整数。 So the values are in the interval [-128, 127] . 所以这些值在区间[-128, 127] If you have a value of 400 and you want to see the actual value for that type, you can subtract the size of the interval from that number until you reach a value that's inside the interval. 如果您的值为400并且希望查看该类型的实际值,则可以从该数字中减去间隔的大小 ,直到达到该区间内的值。

As I said, byte is 8 bit, so the size of the interval is 256 . 正如我所说, byte是8位,所以间隔的大小是256 Subtract that from your initial value: 400 - 256 = 144 . 从初始值中减去: 400 - 256 = 144 This value is still outside of the interval so you have to subtract again: 144 - 256 = -112 . 此值仍然在间隔之外,因此您必须再次减去: 144 - 256 = -112 This value is now inside the interval and is indeed the value you've seen in your test. 此值现在位于区间内,实际上是您在测试中看到的值。

The same is true for your first example: short is 16 bit and signed, so the interval is [-32768, 32767] with size 65536 . 您的第一个示例也是如此: short为16位且已签名,因此间隔为[-32768, 32767] ,大小为65536 Doing repeated subtraction from the value 1921222 will eventually give you the value 20678 as seen in your test. 从值1921222重复减法最终会得到您在测试中看到的值20678

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM