【问题标题】:Weird Result Incrementing a Short Beyond its Maximum Value奇怪的结果增加一个超过其最大值的空头
【发布时间】:2015-01-02 18:49:54
【问题描述】:

当我执行这段代码时,它给出的 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);

    }

【问题讨论】:

    标签: java types range short


    【解决方案1】:

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

    short:short 数据类型是 16 位有符号二进制补码 整数。它的最小值为 -32,768,最大值为 32,767(含)。与字节一样,适用相同的准则:您可以 在大型数组中使用short来节省内存,在这种情况下 节省内存实际上很重要。

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

    /** 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;
    }
    

    【讨论】:

      【解决方案2】:

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

      对我来说,这种类型的问题最好以二进制形式可视化(原因很快就会变得明显):

      你的原始数字(原谅前导零;我喜欢 4 组):

      0001 1110 0010 0100 0000

      然而,根据 Java 语言规范 (JLS) section 4.2,short 是一个 16 位有符号二进制补码整数。将整数值 123456 分配给一个 short 称为“缩小原语转换”,这在 JLS 5.1.3 中有所介绍。具体来说,“有符号整数到整数类型 T 的窄化转换只会丢弃除 n 个最低位之外的所有位,其中 n 是用于表示类型 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,我知道,很疯狂!

      【讨论】:

      • 感谢您的详细解释。我期待这样的答案,因为整数短的不同值给出不同的值,这让我感到困惑!再次感谢!!
      • @Dici,因为它就是这样做的。如果您想要比评论更详细的信息,我帖子中的最后一个链接解释了为什么反转数字并添加一个可以获得二进制补码负值的原因。补码上的Wikipedia entry 对该主题的处理更为严格。
      【解决方案3】:

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

      以下是尝试将 0+123456 存储在 short 中得到 -7616 的方法:

      0 --> 32767
      
      -32768 --> 32767
      
      -32768 --> -7616
      

      换句话说,

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

      【讨论】:

        【解决方案4】:

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

        E1 op= E2 形式的复合赋值表达式是等价的 到E1 = (T) ((E1) op (E2)),其中TE1的类型,除了E1 只评估一次。

        所以

        s += x;
        

        变成

        s = (short) (s + x);
        

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

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

        cast 应用了 narrowing primitive conversion

        [...] 可能会丢失有关 数值的整体大小,也可能会丢失精度和 范围。

        事情就是这样

        s = -7608
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-03
          • 2021-03-25
          • 2013-04-08
          • 2013-04-27
          • 2014-08-01
          相关资源
          最近更新 更多