×

注意!页面内容来自https://blog.csdn.net/wsj66888/article/details/144507661,本站不储存任何内容,为了更好的阅读体验进行在线解析,若有广告出现,请及时反馈。若您觉得侵犯了您的利益,请通知我们进行删除,然后访问 原网页

二进制和位运算

在这里插入图片描述

1.二进制基础

二进制数分为有符号的二进制数和无符号的二进制数

1.1 无符号整数

无符号数是相对有符号数而言,指的是整个机器字长的全部二进制位均表示数值位,相对于数的绝对值。无符号的二进制只能表示非负整数

1.2 有符号整数

既可以表示正数,也可以表示负数,只是符号位不同,正数的符号位为0,负数的符号位为1

1.3 有符号整数和无符号整数的范围

一个无符号的整数有:2n个,其范围是:0~2n
一个有符号的整数有:2n,其中正数有2n-1,负数有2n-1,其范围是:-2n-1~2n-1-1

负数用二进制表示

-5 => 0101 => 0100 => 1011
   1.先找到该负数对应的正数的二进制数
   2.将该二进制数减1
   3.然后再对得到的结果按位一一取反
   得到的结果即为该负数对应的二进制数

判断一个二进制数是那个负数

 1010 => 0101 => 0110 => -6
    1.将该二进制数按位一一取反
    2.将取反后的二进制数加1
    3.得到对应的正数
    则原二进制数对应的负数为该正数的相反数

特例:在该范围内的整数的最小值,他的相反数和绝对值都是自己

假设在 4 个bit位 的情况下-8 这个数字是不能表示为 8 的,
-8:1000 => 0111 => 1000还是8所以不能表示为 8

2.二进制打印函数


// 本文件的实现是用int来举例的
// 对于long类型完全同理
// 不过要注意,如果是long类型的数字num,有64位
// num & (1 << 48),这种写法不对
// 因为1是一个int类型,只有32位,所以(1 << 48)早就溢出了,所以无意义
// 应该写成 : num & (1L << 48)
    
// 打印一个int类型的数字,32位进制的状态
 // 左侧是高位,右侧是低位
    public static void printBinary(int num){
        for (int i = 31; i >= 0; i--) {
            // 下面这句写法,可以改成 :
            // System.out.print((a & (1 << i)) != 0 ? "1" : "0");
            // 但不可以改成 :
            // System.out.print((a & (1 << i)) == 1 ? "1" : "0");
            // 因为a如果第i位有1,那么(a & (1 << i))是2的i次方,而不一定是1
            // 比如,a = 0010011
            // a的第0位是1,第1位是1,第4位是1
            // (a & (1<<4)) == 16(不是1),说明a的第4位是1状态
            System.out.print((num & (1 << i)) == 0 ? "0" : "1");
        }
        System.out.println();
    }

3.十六进制和二进制的直接形式定义

  • 十六进制数:0x4e 可以将4 和 e 分别用四位二进制数进行表示,得到的结果写在一起即为0x4e的二进制形式 0100->4 1110->e 0x4e->01001110
  • 二进制数可用0b加对应的数的二进制来表示

4.常见的位运算

  • 或,与,异或 | & ^(具体运算法则在注释中展示)
       int g = 0b0001010;
       int h = 0b0001100;
       printBinary(g | h);//当g,h上的对应位有一位为1的时候为1,其余是0
       printBinary(g & h);//当g,h上的对应位都为1则为1,其余为0
       printBinary(g ^ h);//g,h对应位上的数字相同则为0,不同则为1
       System.out.println("===g、h===");

上述代码运行结果如下:

00000000000000000000000000001110
00000000000000000000000000001000
00000000000000000000000000000110
===g、h===
  • 左移运算符<<
        int i = 0b0011010;
        printBinary(i);
        printBinary(i << 1);
        printBinary(i << 2);
        printBinary(i << 3);
        System.out.println("===i << ===");

运行结果如下:
00000000000000000000000000011010
00000000000000000000000000110100
00000000000000000000000001101000
00000000000000000000000011010000
左移运算符:原有状态向左移动,右边空出来的位置用0补全

同时,左移n位就相当于原数乘以2n

  • 右移运算符 >> 和 >>>

非负数
两个右移运算符没有区别,运算法则都为将原来的数整体向右移动两位,左边空出的位置用0来补全 例如:
i: 00000000000000000000000000011010
i>>2: 00000000000000000000000000000110
i>>>2:00000000000000000000000000000110

负数
i:11110000000000000000000000000000
i>>2:11111100000000000000000000000000
i>>>2:00111100000000000000000000000000

对于负数来说 >> 当该数右移出相应的位数后,左边空出来的数用1来补全
对于>>> 当该数右移出相应的位数后,左边空出来的数一律用0来补全

同时,右移n位得到的结果相当于原数除以2n只有非负数符合这个特征,负数不要用

左移右移结果如下:       
 int k = 10;
   System.out.println(k);
   System.out.println(k << 1);
   System.out.println(k << 2);
   System.out.println(k << 3);
   System.out.println(k >> 1);
   System.out.println(k >> 2);
   System.out.println(k >> 3);
   System.out.println("===k===");
运行结果如下:
  10
  20
  40
  80
  5
  2
  1
===k===

5.逻辑运算符注意事项

可以这么写 : int num = 3231 | 6434;
可以这么写 : int num = 3231 & 6434;
不能这么写 : int num = 3231 || 6434;
不能这么写 : int num = 3231 && 6434;
因为 ||、&& 是 逻辑或、逻辑与,只能连接boolean类型
不仅如此,|、& 连接的两侧一定都会计算
而 ||、&& 有穿透性的特点

以下通过一段代码来具体解析二者的区别

        System.out.println("test1测试开始");
        boolean test1 = returnTrue() | returnFalse();
        System.out.println("test1结果," + test1);
        System.out.println("test2测试开始");
        boolean test2 = returnTrue() || returnFalse();
        System.out.println("test2结果," + test2);
        System.out.println("test3测试开始");
        boolean test3 = returnFalse() & returnTrue();
        System.out.println("test3结果," + test3);
        System.out.println("test4测试开始");
        boolean test4 = returnFalse() && returnTrue();
        System.out.println("test4结果," + test4);
        System.out.println("===|、&、||、&&===");
        
    public static boolean returnTrue() {
        System.out.println("进入了returnTrue函数");
        return true;
    }

    public static boolean returnFalse() {
        System.out.println("进入了returnFalse函数");
        return false;
    }

运行结果如下:

  1. test1测试开始
    进入了returnTrue函数
    进入了returnFalse函数
    test1结果,true
    2.test2测试开始
    进入了returnTrue函数
    test2结果,true
    3.test3测试开始
    进入了returnFalse函数
    进入了returnTrue函数
    test3结果,false
    4.test4测试开始
    进入了returnFalse函数
    test4结果,false
    =|、&、||、&&=

由此可见,普通的 | 和 & 运算符左右两侧都会被计算,而逻辑或 || 和逻辑与 &&,因其具有穿透性的特点,不会被全部计算,只要找到符合条件的情况就会停止

确定要放弃本次机会?
福利倒计时
: :

立减 ¥

普通VIP年卡可用
立即使用
参与评论 您还未登录,请先 登录 后发表或查看评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
点击重新获取
扫码支付
< type="text/css">
钱包余额 0

抵扣说明:

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

余额充值