打印数字的位信息

数据底层都是二进制组成,如何打印int 和 long类型数字的位信息?

int 类型为基本数据类型,占4字节,32位。long类型也为基本数据类型,占8字节,84位。

这里需要用的 “&” 与运算。

& : 与运算,当两个数字执行此运算,会在底层比较二进制信息,逐个值对比,然后返回计算后新生成的数据。规则为:将二进制的数据进行对比,如果两个数均为1,则生成的新数据的这个位置为1;如果这个位置上两个数据的值 不是都为1则将这个位置赋值为0。

例:

    @Test
    public void test2() {
        int a = 123;    //00000000000000000000000001111011
        int b = 1340;   //00000000000000000000010100111100

        //两个位置都是1 才会出1,否则其他都是0
        printI(a&b);   //通过自定义的方法打印位信息
        System.out.println(a&b); //56
                        //00000000000000000000000000111000
        
    }

结合 "<<" (左移) 位运算,逐个去对比,得到结果,然后打印出来。

1的位信息: 00000000000000000000000000000001 ,让1一位一位的左移 去跟数据进行对比

private void printI(int num) {
        for (int i = 31; i >= 0; i--) {
            // & 与运算 (0与0,0与1相遇为0)
            //因为这个特性,左移位的数字与num与运算,如果不是1,则得到32位0,数值为0
            System.out.print((num & (1 << i)) == 0 ? "0" : "1");
        }
        System.out.println();
    }

第一次先将1左移31位,到达最左侧,10000000000000000000000000000000,去与这个num 进行与运算,如果这个位置上不为1,则会返回00000000000000000000000000000000,结果为0,此时打印0,如果不为0,则打印1,就可以得到这个整数的 位信息了。(如果为1,返回的新数肯定不为0)。

打印64位信息也一个原理:

//打印64位信息 用与& 运算实现
    private void printL(long num) {
        for (int i = 63; i >= 0; i--) {
            System.out.print((num & (1L << i)) == 0 ? "0" : "1");
        }
        System.out.println();
    }

    @Test
    public void testLong() {
        long start = System.nanoTime();
        long num1 = 1L;
        long num2 = 2L;
        long num = 123L;
        printL(num1);
        printL(num2);
        printL(num);
        long end=System.nanoTime();
        System.out.println(end-start);
     /*
     0000000000000000000000000000000000000000000000000000000000000001
     0000000000000000000000000000000000000000000000000000000000000010
     0000000000000000000000000000000000000000000000000000000001111011
     */
    }

& 与运算:两个数进行“&”与运算,二进制数据进行对比,如果两数不相同则返回0,两个数都为1则这个位置返回一个1。

| 或运算:两个数进行 “|”或运算,二进制数据进行对比,如果有一个为1,则这个位置返回1。

^ 异或运算:两个数进行“^”异或运算,二进制数据进行对比,如果两个数一致,则这个位置返回0,如果不一致,这个位置返回1

  //或 |  异或^
    @Test
    public void test2() {
        int a = 123;
        int b = 1340;
        printI(a);
        printI(b);
        System.out.println("===============");
        //两个数或运算,只要有一个地方有1,其他都变1
        printI(a | b);
        //两个位置都是1 才会出1,否则其他都是0
        printI(a & b);
        //两个位置相同 就为0 不同为1
        printI(a ^ b);

        /*00000000000000000000000001111011
          00000000000000000000010100111100
          ===============
          00000000000000000000010101111111
          00000000000000000000000000111000
          00000000000000000000010101000111*/
    }

位运算:<< 无符号左移(右移才有带符号右移)

//位运算 左移位 及 &与运算,左移位都是无符号,只有右移才是有符号
    //数字左移一位,相当于num*2
    @Test
    public void testLeft() {
        //左移位运算 1向左移动31位,剩余的用0补上 比如 1<<31
        //1向左移动1位,剩余用0补全 为2
        System.out.println(1 << 1);
        //左移2位 位4
        System.out.println(1 << 2);
        System.out.println(1 << 31);
        // & 与运算
        System.out.println(2 & (1 << 0));
        //运算为:2的0次方+2的1次方+2的2次方,1只有一个1,2的0次方
        int num = 1;
        int num1 = 2345;
        printI(num);
        printI(num << 1);
        printI(num1);
        printI(num1 << 1);
    }

~ 取反,0变为1,1变为0 ,最左的位置为符号位。

~a+1 = -a 用这种逻辑,方便运算,后续运算都用一套逻辑。

//整型最大值及 正负数如何表示?32位最多能表示40多亿 2的32次方 -1;(因为0要算上,所以最大值要-1)
    //0归属在非负区域,负数最小值 绝对值能达到2的31次方,取反最后+1,就把符号位占用了。
    //实际上 int 最多是20多亿 2的31次方-1 ,因为有正负,如果无符号数,就可以都用了40多亿 ,所以无符号的最大值比有符号的最大值大
    @Test
    public void test() {
        //正型 真正表示值的范围是 0位到30位的范围,最高位留着既可以表示正,也可以表示负
        int max = Integer.MAX_VALUE;
        System.out.println(max); //2147483647
        printI(max);  //01111111111111111111111111111111
        //最高位是0 则此数肯定不是负数
        int min = Integer.MIN_VALUE;
        System.out.println(min);  //-2147483648
        printI(min);   //10000000000000000000000000000000
        System.out.println("01111111111111111111111111111111".length());
        //int的范围是 -2的31次方~2的31次方-1
        //如果是负数,符号位一定是1,符号位以外的数全部取反,末尾+1,则表示值是多少
        printI(-1);  //11111111111111111111111111111111 符号位以外的,全部取反1变为0...0;末尾+1以后的值 就为具体值;
        printI(-2);  //11111111111111111111111111111110
        printI(-3);  //11111111111111111111111111111101 全部取反为10000000000000000000000000000010 +1  ->10000000000000000000000000000011
    }

    //取反 ;负数的值就是 取反+1
    @Test
    public void test1() {
        int a = 1349811;
        //取反操作
        int b = -a;
        //打印32位数
        printI(a);  //00000000000101001001100010110011
        printI(b);  //11111111111010110110011101001101 全部相反,取反后+1则为值
        //取反操作+1 ,就是负的
        int b1 = (~a + 1);
        printI(b1); //11111111111010110110011101001101
        //整数最小数取反 及0取反
        System.out.println("===最小数取反+1及0取反是自己=====");
        int min = Integer.MIN_VALUE;
        printI(min);
        printI(~min); //取反
        //取反+1
        printI(~min + 1);
        printI(0);
        printI(-0);
        /*
        ===最小数取反+1及0取反是自己=====
        10000000000000000000000000000000
        01111111111111111111111111111111
        10000000000000000000000000000000
        00000000000000000000000000000000
        00000000000000000000000000000000
         */
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Laughing_Xie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值