3

short我对Java 中的数据类型有一个疑问。我知道简写的范围在 -32768 到 32767 之间。

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

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

结果是-5536

所以数学是32768 + 32768 = 655366000 - 65536 = -5536

我知道它做了什么,但我不知道为什么它会这样。

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

4

4 回答 4

7

正在发生的事情是你的号码正在环绕。更具体地说,你有一个数字 30,000,二进制是:

0111 0101 0011 0000

当您将其添加到自身并携带 1 时,您会得到:

1110 1010 0110 0000

(注意:在二进制中将一个数字乘以 2 非常容易——只需将所有位向左移动一位。)

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

如果再次将该数字乘以 2,则需要 2 个以上的字节来表示它。由于 a 中没有超过 2 个字节,因此当表达式的结果缩小到 ashort时,多余的位就会被丢弃。做到这一点,你会得到一个 0 作为最左边的数字;该数字再次为正。然后最终您将再次将 1 作为最左边;这个数字又是负数了。最终你会将所有的 0 移到数字中;将任何整数乘以 2 足够的次数总是会得到 0(具体来说,如果它是一个 N 位数,那么将它乘以 2 N 次总是会得到 0)。intshort

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

于 2012-08-16T15:39:19.557 回答
4

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

结果是int tmp = 60000;

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

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

换句话说60000 = 1110 1010 0110 0000b,但是 short 是有符号的,所以最初的 1 是符号并且使用 2 补码,你会得到等效的 short 值,即 -5536:1110 1010 0110 0000=> - 0001 0101 1010 0000(你否定所有位,加一个并放一个减号)

于 2012-08-16T15:50:37.603 回答
3
    0111 0101 0011 0000
  + 0111 0101 0011 0000
  ______________________
    1110 1010 0110 0000 

Javashort是用二进制补码编码的。在二进制补码中,最高有效位被认为是符号位,0是正数1和负数。

1110 1010 0110 0000 = -5536 in two's complement
于 2012-08-16T15:39:58.080 回答
2

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

0010 = 2

要翻转符号,请将所有 0 替换为 1,然后添加 1:

-2 = 1110

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

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

于 2012-08-16T15:36:41.080 回答