奇怪的结果增加了一个超过其最大值的短路

Weird Result Incrementing a Short Beyond its Maximum Value

当我执行这段代码时,它给出的 s 值为 -7616。 为什么这样?这是因为在将其从 int 或其他东西转换为 short 时丢失了数据吗?

public static void main(String[] args) {
        // TODO code application logic here
       short s=0;
       int x=123456;
       int i=8;
       s +=x;
       System.out.println(s);

    }

你只是溢出了 short 的最大值:

short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.

当出现这种溢出时会发生什么,相当于这个算法:

/** Returns an integer which is equal to the short obtained by the ((short) n) conversion */
public static int int2short(int n) {
    int sign      = n > 0 ? 1 : -1;
    int increment = sign * (Short.MAX_VALUE - Short.MIN_VALUE + 1);
    for ( ; n > Short.MAX_VALUE || n < Short.MIN_VALUE ; n -= increment);
    return n;
}

short 增加到超过其最大值称为溢出。当发生溢出时,该值变为该类型的最小值,并重新开始向上计数。

所以这就是你如何通过尝试将 0+123456 存储在 short 中得到 -7616:

0 --> 32767

-32768 --> 32767

-32768 --> -7616

换句话说,

32768+ 32768+ 32768+ (32768 -7616) = 123456

复合赋值运算符+=(全部都是真的)cast their result

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

所以

s += x;

变成

s = (short) (s + x);

现在,因为 sshortxintbinary numeric promotion is performed on the short value before the addition is applied. short 值被转换为int(这不是问题)。

s = (short) (8 + 123456)
s = (short) (123464)

cast applies a narrowing primitive conversion其中

[...] may lose information about the overall magnitude of a numeric value and may also lose precision and range.

就是这样

s = -7608

好问题!这让我想到了很久没有想过的事情,我不得不重温几个概念。谢谢你帮我敲掉脑子里的铁锈。

对我来说,这种类型的问题最好用二进制表示(原因很快就会变得明显):

您的原始号码(请原谅前导零;我喜欢 4 组):

0001 1110 0010 0100 0000

但是,根据 Java 语言规范 (JLS) section 4.2. Assigning the integer value 123456 to a short is known as a "narrowing primitive conversion" which is covered in JLS 5.1.3,短整型是一个 16 位有符号二进制补码整数。具体来说,"narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T."

丢弃除最低 16 位以外的所有位,我们得到:

1110 0010 0100 0000

在无符号整数中,该值为 57,290,但短整数是有符号二进制补码整数。最左边的 1 表示负数;要获得数字的值,您必须 invert the bits and add 1:

原文:

1110 0010 0100 0000

反转位:

0001 1101 1011 1111

加1:

0001 1101 1100 0000

将其转换为十进制并加上负号得到 -7,616.

再次感谢您提出问题。不知道某事没关系,所以要不断提问和学习。我很高兴回答...我喜欢深入 JLS,疯狂,我知道!