奇怪的结果增加了一个超过其最大值的短路
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);
现在,因为 s
是 short
而 x
是 int
,binary 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,疯狂,我知道!
当我执行这段代码时,它给出的 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 toE1 = (T) ((E1) op (E2))
, whereT
is the type ofE1
, except thatE1
is evaluated only once.
所以
s += x;
变成
s = (short) (s + x);
现在,因为 s
是 short
而 x
是 int
,binary 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,疯狂,我知道!