时不时地会被这两个绕一下,干脆写个demo加深记忆。

背景知识

  • java 中的整型int占4个字节,也就是32位,首位为符号位,0表示正数,1表示负数。
  • 计算机中数值采用补码的方式存放

Java友元类吗 java有友元吗_补码

规律

  • 首位为符号位,0表示正数,1表示负数
  • 正整数的原码、反码、补码 三码合一
  • 负整数的反码:符号位不变,其余按位取反
  • 负整数的补码:反码+1,也就是符号位不变,其余按位取反,然后再加上1
  • 补码的补码等于原码

ps: java中可以使用Integer.toBinaryString()来获取一个整数的补码表示,注意这里是补码,不是原码,原码=补码的补码。

有符号右移运算>>

1.将正整数11有符号右移3位:

+11>>

Java友元类吗 java有友元吗_补码_02

很容易看出:

对于正整数:有符号右移n位,结果的补码等于在高位补了n个0,低位溢出舍弃

正整数原码、反码和补码 三码合一,所以不需要操心太多。

2.将负整数-11有符号右移3位:

-11>>

Java友元类吗 java有友元吗_整型_03

注意注意,这里的结果是补码哦。

根据补码的补码等于原码规律,可以求出原码是:10000000000000000000000000000010,换算成整数是-2

对于负整数:有符号右移n位,结果的补码等于在补码的高位补了n个1,低位溢出舍弃

注意是结果的补码,不是原码。

无符号右移运算>>

1.将正整数11无符号右移3位:

+11>>>

Java友元类吗 java有友元吗_整型_04

这里跟有符号右移是一样的。

2.将负整数-11无符号右移3位:

-11>>>

Java友元类吗 java有友元吗_Java友元类吗_05

可以看出是在高位补了3个0哈。

对于负整数:无符号右移n位,结果的补码等于在补码的高位补了n个0,低位溢出舍弃

所以无符号右移,对于正整数和负整数,结果的补码都等于是在高位补0.

正整数无符号右移一位等于除以2再向下取整

补充一点,一个正整数,无符号右移一位等于这个整数除以2,再向下取整。

4>>>1,结果为2;5>>>1,结果为2

原理很容易想明白,比如5的二进制是101,右移一位得到010,也就是整数2.

注意,只有正整数可以这样算噢,正整数三码合一,负整数原码补码不一样,不能这样算的噢。

源代码:

/**
 *  有符号右移和无符号右移
 */
public class RightShift {

    public static void main(String args[]){
        RightShift rightShift = new RightShift();
        rightShift.signedRightShift(11);
        rightShift.signedRightShift(-11);
        rightShift.unsignedRightShift(11);
        rightShift.unsignedRightShift(-11);
    }

    /**
     *  有符号右移
     * @param n
     */
    public void signedRightShift(int n){
        System.out.println(n+"的有符号右移...........");
        System.out.println("参数整型是:"+n);
        System.out.println("参数补码是:"+Integer.toBinaryString(n));
        int a = n>>3; // 有符号右移三位
        System.out.println("结果整型是:"+a);
        System.out.println("结果补码是:"+Integer.toBinaryString(a));
    }

    /**
     * 无法符号右移
     * @param n
     */
    public void unsignedRightShift(int n){
        System.out.println(n+"的无符号右移...........");
        System.out.println("参数整型是:"+n);
        System.out.println("参数补码是:"+Integer.toBinaryString(n));
        int a = n>>>3; // 无符号右移三位
        System.out.println("结果整型是:"+a);
        System.out.println("结果补码是:"+Integer.toBinaryString(a));
    }
}