【问题标题】:Signed left shift behaviour有符号左移行为
【发布时间】:2013-04-17 01:05:06
【问题描述】:
public class Shift {

    public static void main(String[] args) {
        for(int i = 0; i < 32; ++i){
            System.out.println(-0x55555555 << i);
        }
    }

}

运行上面的代码会得到以下输出

-1431655765
1431655766
-1431655764
1431655768
-1431655760
1431655776
-1431655744
1431655808
-1431655680
1431655936
-1431655424
1431656448
-1431654400
1431658496
-1431650304
1431666688
-1431633920
1431699456
-1431568384
1431830528
-1431306240
1432354816
-1430257664
1434451968
-1426063360
1442840576
-1409286144
1476395008
-1342177280
1610612736
-1073741824
-2147483648

虽然使用其他值 (64) 进行测试会得到更符合预期的结果

public class Shift {

    public static void main(String[] args) {
        for(int i = 0; i < 32; ++i){
            System.out.println(-0x40 << i);
        }
    }

}

输出

-64
-128
-256
-512
-1024
-2048
-4096
-8192
-16384
-32768
-65536
-131072
-262144
-524288
-1048576
-2097152
-4194304
-8388608
-16777216
-33554432
-67108864
-134217728
-268435456
-536870912
-1073741824
-2147483648
0
0
0
0
0
0

the specs (§15.19) 中说:

The value of n &lt;&lt; s is n left-shifted s bit positions; this is equivalent (even if overflow occurs) to multiplication by two to the power s.

有人可以解释第一个输出的原因吗?

【问题讨论】:

    标签: java int bit-shift signed


    【解决方案1】:

    n

    确实如此:由于溢出,这正是您将 -0x55555555 乘以 s 的 2 次方得到的结果。特别是,0x55555555 具有交替的 0 和 1,因此您将交替的 0 和 1 移入符号位,因此符号每次都在翻转。

    【讨论】:

    • 那么为什么它在第二个示例中保留标志?究竟什么是溢出?
    • 它保留第二个示例中的符号,因为-0x40 在其二进制表示中没有交替的 0 和 1;它的二进制表示是0xFFFFFFC0,所以当你把它左移时它的符号位仍然是1(直到你把它移到0为止)。
    • 溢出将是“通常”超出范围 -2^31
    • 没关系溢出的东西。我不知道为什么我认为 -0x40 为 0x80000040 ...完全搞砸了 2 的补码表示。谢谢 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多