<< >> >>>

package ssss;

public class dwd {
    public static void main(String[] args) {
        // 看二进制表示,最高位是1就是负数,值0就是正数。
        System.out.println("------负数左移------------------------------------------------------");
        int i = -6; // 负数左移
        System.out.println(Integer.toBinaryString((int) i));
        // 正6: 0000-0000 0000-0000 0000-0000 0000-0110
        // 取反:1111-1111 1111-1111 1111-1111 1111-1001
        // 加一 补码:1111-1111 1111-1111 1111-1111 1111-1010

        System.out.println(Integer.toBinaryString((int) (i << 28)));
        // 补码:1010-0000 0000-0000 0000-0000 0000-0000
        // 减一:1001-1111 1111-1111 1111-1111 1111-1111
        // 取反:0110-0000 0000-0000 0000-0000 0000-0000 -(2^29+2^30)=-1610612736
        System.out.println((int) (i << 28));

        System.out.println(Integer.toBinaryString((int) (i << 29)));
        // 补码:0100-0000 0000-0000 0000-0000 0000-0000
        System.out.println((int) (i << 29));// 2^30=1073741824

        System.out.println("------正数左移------------------------------------------------------");
        int j = 6; // 正数左移
        System.out.println(Integer.toBinaryString((int) j));
        // 正6 补码: 0000-0000 0000-0000 0000-0000 0000-0110

        System.out.println(Integer.toBinaryString((int) (j << 28)));
        // 补码:0110-0000 0000-0000 0000-0000 0000-0000 (2^29+2^30)=1610612736
        System.out.println((int) (j << 28));

        System.out.println(Integer.toBinaryString((int) (j << 29)));
        // 补码:1100-0000 0000-0000 0000-0000 0000-0000
        // 减一 1011-1111 1111-1111 1111-1111 1111-1111
        // 取反0100-0000 0000-0000 0000-0000 0000-0000 -2^30=1073741824
        System.out.println((int) (j << 29));

        System.out.println("------正数右移------------------------------------------------------");
        int k = 6; // 正数右移
        System.out.println(Integer.toBinaryString((int) k));
        // 正6 补码: 0000-0000 0000-0000 0000-0000 0000-0110

        System.out.println(Integer.toBinaryString((int) (k >> 2)));
        // 补码:0000-0000 0000-0000 0000-0000 0000-0001
        System.out.println((int) (k >> 2)); // 1

        System.out.println(Integer.toBinaryString((int) (k >>> 2)));// 无符号右移
        // 补码:0000-0000 0000-0000 0000-0000 0000-0001
        System.out.println((int) (k >>> 2)); // 1

        System.out.println(Integer.toBinaryString((int) (k >> 3)));
        // 补码:0000-0000 0000-0000 0000-0000 0000-0000
        System.out.println((int) (k >> 3));// 0

        System.out.println(Integer.toBinaryString((int) (k >>> 5)));// 无符号右移
        // 补码:0000-0000 0000-0000 0000-0000 0000-0000
        System.out.println((int) (k >>> 5));// 0

        System.out.println("------负数右移------有符号无符号右移------------------------------------------------");
        int l = -6; // 负数右移
        System.out.println(Integer.toBinaryString((int) l));
        // 正6 : 0000-0000 0000-0000 0000-0000 0000-0110
        // 取反: 1111-1111 1111-1111 1111-1111 1111-1001
        // 加一 补码: 1111-1111 1111-1111 1111-1111 1111-1010

        System.out.println(Integer.toBinaryString((int) (l >> 28)));// 右移的规则只记住一点:符号位不变,左边补上符号位1
        // 补码:1111-1111 1111-1111 1111-1111 1111-1111
        System.out.println((int) (l >> 28)); // -1
        // 减一 1111-1111 1111-1111 1111-1111 1111-1110
        // 取反:0000-0000 0000-0000 0000-0000 0000-0001

        System.out.println(Integer.toBinaryString((int) (l >>> 28)));// 无符号右移,忽略了符号位扩展,0补左边
        // 补码:0000-0000 0000-0000 0000-0000 0000-1111
        System.out.println((int) (l >>> 28)); // 15

        System.out.println("------0xff------------------------------------------------------");

        System.out.println(Integer.toBinaryString(0xff)); // 0000-0000 0000-0000 0000-0000 1111- 1111
        System.out.println(Integer.toBinaryString(0xffff)); // 0000-0000 0000-0000 1111-1111 1111- 1111
        System.out.println(Integer.toBinaryString(0xfffff)); // 0000-0000 0000-1111 1111-1111 1111- 1111
        System.out.println(Integer.toBinaryString(0xfffffff)); // 0000-1111 1111-1111 1111-1111 1111- 1111
        System.out.println(Integer.toBinaryString(0xffffffff)); // 1111-1111 1111-1111 1111-1111 1111- 1111
        //    System.out.println( Integer.toBinaryString(0xfffffffff) ); //异常
    }
}
/*
 1、 左移运算符
     左移的规则只记住一点:丢弃最高位,0补最低位
     如果移动的位数超过了该类型的最大位数,那么编译器会对移动的位数取模。如对int型移动33位,实际上只移动了33/32=1位。
     在数字没有溢出的前提下,对于正数和负数,左移一位都相当于乘以2的1次方,左移n位就相当于乘以2的n次方
    2、 右移运算符
            右移的规则只记住一点:符号位不变,左边补上符号位:低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1
            当右移的运算数是byte 和short类型时,将自动把这些类型扩大为 int 型。
           在数字没有溢出的前提下,右移一位相当于除2,右移n位相当于除以2的n次方。
   3、无符号右移
          无符号右移的规则只记住一点:忽略了符号位扩展,0补最高位  
          无符号右移规则和右移运算是一样的,只是填充时不管左边的数字是正是负都用0来填充,无符号右移运算只针对负数计算,因为对于正数来说这种运算没有意义(一样的)
   
   
 1.有符号和无符号的概念如下:
     最明显的区别就是二者表示的范围不同: 无符号数中,所有的位都用于直接表示该值的大小。有符号数中最高位用于表示正负,所以,当为正值时,该数的最大值就会变小。
     无符号数: 1111 1111 值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 
    有符号数: 0111 1111 值:127 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 
    同样是一个字节,无符号数的最大值是255,而有符号数的最大值是127。 所以无符号数比有符号数的最大值大1倍。
    我们仍一个字节的数值对比: 
    无符号数: 0 ----------------- 255 有符号数: -128 --------- 0 ---------- 127  
    所以二者能表达的不同的数值的个数都一样是256个。 只不过前者表达的是0到255这256个数,后者表达的是-128到+127这256个数
 2.java没有无符号类型,都是有符号类型的数据类型
     在实际开发中,可能要与c写的硬件接口,网络接口相互直接数据交互,此时由于java没有无符号的数据类型,导致java与c看似相同的数据类型,
     其实存储空间确是不同的,这个问题解决方法是java用更高的存储数据类型,如果c用int,你的java就要考虑用Long或者BigInteger了
 
 */

原文地址:https://www.cnblogs.com/yaowen/p/10848705.html