在Java中溢出Short

我有一个关于Java中的short数据类型的问题。 我知道短期的范围在-32768到32767之间。

因此,如果我尝试添加两个超出范围的短值,则结果最终为假定的总减去正范围或负范围乘以2,如下所示:

 short a = 30000; a = (short) (a+a); 

结果是-5536

所以数学是32768 + 32768 = 65536,6000 – 65536 = -5536

我知道它的作用,但我不知道为什么会这样做。

任何人都可以解释逻辑或为什么Java这样做?

发生了什么事情,你的号码正在四处传播。 更具体地说,你有一个30,000,二进制是:

 0111 0101 0011 0000 

当你把它添加到自己,并携带1,你得到:

 1110 1010 0110 0000 

(注意:在二进制中将数字乘以2很容易 – 只需将所有位向左移一步。)

短是使用二进制补码的带符号数,意味着最左边的1实际上是一个减号; 该数字代表-5536。

如果再次将该数字乘以2,则需要超过2个字节来表示它。 由于short不超过2个字节,因此当表达式的int结果缩小为short ,额外的位将被删除。 做到这一点,你将得到一个0作为最左边的数字; 这个数字又是正数。 然后最终你将再次作为最左边的1; 这个数字又是负数。 最终你将所有0都转换为数字; 将任何整数乘以2足够的时间总是会得到0(具体来说,如果它是一个N位数,则乘以2 N次将总是得到0)。

如果你没有缩小到一个short ,你仍然最终会用完int的数字(当你需要33位或更多位时) – 这会导致额外的数字被丢弃,这是整数溢出 。 如果任何一个参数都很long ,同样的事情会发生,尽管它需要65+位。

首先,您的添加将short转换为int,因为加法运算符对操作数执行二进制数字提升 。

因此结果是int tmp = 60000;

然后通过缩小的原始转换将该结果转换回short:

将有符号整数缩小到整数类型T只会丢弃除n个最低位之外的所有位,其中n是用于表示类型T的位数。

换句话说, 60000 = 1110 1010 0110 0000b但是签名为short,因此初始1是符号并使用2补码,您得到等效的短值,即-5536: 1110 1010 0110 0000 => – 0001 0101 1010 0000 (您否定所有位,添加一个并放一个减号)

  0111 0101 0011 0000 + 0111 0101 0011 0000 ______________________ 1110 1010 0110 0000 

Java的short二进制编码。 在二进制补码中,最高有效位被视为符号位, 0为正, 1负。

 1110 1010 0110 0000 = -5536 in two's complement 

它与数据的二进制表示有关。 在大多数系统中,使用称为2的补码。 正数表示正常,只要它们具有前导0即可。

 0010 = 2 

要翻转标志,将所有0替换为1,并添加1:

 -2 = 1110 

那么如果我们采用最大的正数,比如01111(二进制),加1,会发生什么? 我们得到10000,这是一个负数(特别是Int.min_val)。 当整数溢出时会发生这种情况。

http://en.wikipedia.org/wiki/Two%27s_complement