Java 奇怪的结果,使短值增加到超过其最大值
当我执行这段代码时,它给出s的值为-7616。 为什么会这样?这是因为从int或其他内容转换为short时丢失了数据吗Java 奇怪的结果,使短值增加到超过其最大值,java,types,range,short,Java,Types,Range,Short,当我执行这段代码时,它给出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); }
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数据类型是16位有符号2的补码 整数。它的最小值为-32768,最大值为 32767(含)。对于byte,同样的准则也适用:您可以 在出现以下情况时,请使用短消息在大型阵列中节省内存: 节省内存实际上很重要 出现这种溢出时发生的情况与此算法等效:
/** 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)n)转换获得的short*/
公共静态int int2short(int n){
整数符号=n>0?1:-1;
int增量=符号*(Short.MAX\u值-Short.MIN\u值+1);
对于(;n>Short.MAX_值| | n将short
增加到其最大值之外称为溢出。发生溢出时,该值将成为该类型的最小值,并再次开始计数
下面是您如何通过尝试在short
中存储0+123456得到-7616的:
0 --> 32767
-32768 --> 32767
-32768 --> -7616
换句话说,
32768+ 32768+ 32768+ (32768 -7616) = 123456
复合赋值运算符+=
(它们都是真的)
形式为E1 op=E2
的复合赋值表达式是等效的
toE1=(T)((E1)op(E2))
,其中T
是E1
的类型,除了E1
仅评估一次
所以
变成
s = (short) (s + x);
现在,由于s
是short
且x
是int
,因此short
值被转换为int
(这不是问题)
适用于
[…]可能会丢失有关
数值的总大小,也可能会失去精度和
射程
事情就是这样
s = -7608
好问题!它让我想到了一些我很久没想到的事情,我不得不温习一些概念。谢谢你帮我把脑子里的锈去掉
对我来说,这类问题最好以二进制形式呈现(原因很快就会变得显而易见):
您的原始数字(请原谅前导的零;我喜欢4人一组):
0001 1110 0010 0100 0000
然而,根据Java语言规范(JLS),short是一个16位带符号2的补码整数。将整数值123456分配给短路称为“缩小原语转换”,这将在中介绍。具体来说,“有符号整数到整数类型T的窄化转换只会丢弃除n个最低阶位以外的所有位,其中n是用于表示类型T的位数。”
丢弃除最低16位以外的所有位会给我们留下:
1110 0010 0100 0000
在无符号整数中,该值为57290,但短整数是有符号2的补码整数。最左边数字中的1表示负数;要获取数字的值,必须:
原件:
1110 0010 0100 0000
反转位:
0001 1101 1011 1111
加1:
0001 1101 1100 0000
将其转换为十进制并添加负号以获得-7616
再次感谢你提出这个问题。不知道也没关系,所以继续问下去,继续学习。我回答得很开心…我喜欢跳进JLS,疯狂,我知道 谢谢你的详细解释。我期待这样的答案,因为在不同的整数短值给出不同的值,这让我困惑!再次感谢@迪奇,因为事情就是这样做的。如果你想要更多的细节,而不是在评论中,我文章的最后一个链接解释了为什么倒数加1可以得到两个负数的补码。《论二》的补语对这一主题的处理更为严格。
s = (short) (8 + 123456)
s = (short) (123464)
s = -7608