zoukankan      html  css  js  c++  java
  • 一文带你深入理解位运算

    前言

    相信同学们听到“位运算”这个词都很熟悉,但是在实际应用中却很少涉及,上至十几年的老程序员,下至两三年的菜鸟,可能都没有真正弄懂过,今天就带大家深入地理解学习一遍。

    程序中的所有数在计算机内存中都是以二进制的形式储存的。位运算说穿了,就是直接对整数在内存中的二进制位进行操作。运位算包括位逻辑运算移位运算,位逻辑运算能够方便地设置或屏蔽内存中某个字节的一位或几位,也可以对两个数按位相加等;移位运算可以对内存中某个二进制数左移或右移几位等。

    一. 简介

    Java提供了七种位运算

     位运算符  名称  含义  举例
     & 按位与

    将参与运算的两个二进制数进行&与运算,如果两个二进制位都是1,则与运算的结果为1,其他全都为0。(0与任意数N&运算都是0)

    a&b
     | 按位或

    将参与运算的两个二进制数进行|或运算,两个二进制位只要其中1个是1 ,那么就是1,如果2个二进制位都是0则表示0。(0与任意数N|运算都是任意数N)

    a|b 
    按位异或 将参与运算的两个二进制数进行^异或运算,如果2个二进制位都是0或者都是1,那么就是0,如果两个二进制位不同,则为1。  a^b
    按位非 一元操作符,按位取反。每个二进制位上都取相反值,1变成0,0变成1。  ~a
    <<  左移 将一个数各二进制位全部向左移动若干位,左移运算没有有符号和无符号左移动,在左移时,移除高位的同时在低位补0 a<<2 
    >>  右移 又称为有符号右移。将一个数各二进制位全部向右移动若干位,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。 a>>2 
    >>>  无符号右移  将一个数各二进制位全部向右移动若干位,右移之后左边都是补上0。忽略符号位   a>>>2
     

     

    由位运算操作符衍生而来的有:

    &= 按位与赋值,|=  按位或赋值,^= 按位非赋值,<<= 赋值左移,>>= 右移赋值,>>>= 无符号右移赋值

    (和 += 一个概念)

     

    二. 实操

    我们以0、1、2、4、8、16、32这几个数来演示下各运算符的逻辑,首先我们计算出这几个数的二进制分别是:

     0  的二进制数为: 0000 0000 0000 0000
     1  的二进制数为: 0000 0000 0000 0001
     2  的二进制数为: 0000 0000 0000 0010
     4  的二进制数为: 0000 0000 0000 0100
     8  的二进制数为: 0000 0000 0000 1000
    16 的二进制数为: 0000 0000 0001 0000
    32 的二进制数为: 0000 0000 0010 0000

    2.1. &按位与运算

    将参与运算的两个二进制数进行&与运算,如果两个二进制位都是1,则与运算的结果为1,其他全都为0。(0与任意数N&运算都是0)

    判断奇偶:n & 1 == 1则为奇数,n & 1 == 0则为偶数

    判断是否是2的整数次幂:n & (n-1) == 0是2 ^ n,n & (n-1) == 1不是2 ^ n

    0&2 = 0
    0&4 = 0
    2&4 = 0
    2&8 = 0
    4&12= 4

    2.2. |按位或运算:

    将参与运算的两个二进制数进行|或运算,两个二进制位只要其中1个是1 ,那么就是1,如果2个二进制位都是0则表示0。(0与任意数N|运算都是任意数N)

    0|2 = 2
    0|4 = 4
    2|4 = 6
    2|8 = 10

    2.3. ^按位异或运算

    将参与运算的两个二进制数进行^异或运算,如果2个二进制位都是0或者都是1,那么就是0,如果两个二进制位不同,则为1。

    0^2 = 2
    0^4 = 4
    2^4 = 6
    2^8 = 10

    2.4. ~按位非运算

    一元操作符,按位取反。每个二进制位上都取相反值,1变成0,0变成1。

    ~0 = -1
    ~1 = -2
    ~2 = -3
    ~4 = -5
    ~8 = -9

    2.5. 左移(<<)

    将一个数各二进制位全部向左移动若干位,左移运算没有有符号和无符号左移动,在左移时,移除高位的同时在低位补0

    左移1位相当于乘2,x << n等价于x * (2 ^ n)。

    2<<1 = 4
    2<<2 = 8
    2<<3 = 16
    2<<4 = 32

    2.6. 右移(>>又称为有符号右移)

    将一个数各二进制位全部向右移动若干位,若参与运算的数字为正数,则在高位补0;若为负数,则在高位补1。

    右移1位相当于除2,x >> n等价于x / 2n。

    32>>1 = 16
    32>>2 = 8
    32>>3 = 4
    32>>4 = 2

    2.7. 无符号右移(>>>)

    将一个数各二进制位全部向右移动若干位,右移之后左边都是补上0。忽略符号位

    32>>>1 = 16
    32>>>2 = 8
    32>>>3 = 4
    32>>>4 = 2

    二. 原码、反码、补码

    一个数,取绝对值大小转换为二进制数,称其为原码。正常情况下,对计算机的俩个数进行加法运算,由于不知道符号,所以对其取补码后进行运算,正数的补码是其本身,负数的补码是对其正数取反加1。
    原码:正数的原码是本身,负数的原码是其正数的原码,并将最高位改为1。

    以5为例:

    5的二进制数(即原码):0000 0000 0000 0101

    原码:0000 0101

    反码:1111 1010

    补码:1111 1011   (负数的补码是对其正数取反加1)

    即得到-5的二进制数:1111 1011

    三. 实例

    把一个整数拆成2的n次方的数相加
    public void pow2() {
        int input = 19;
        int m = 1;
        for (int i =1; i< 32; i++) {
            if((m & input) == m) {
                System.out.println(m);
            }
    
            m = m << 1;
            if(m > input) {
                break;
            }
        }
    }
    作者:mrluo735

    -------------------------------------------

    个性签名:恬淡的生活态度,适当的坚持付出,散发出你闪耀的人生哲学!

    如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个 [推荐]哦,博主在此感谢!

    万水千山总是情,打赏一分行不行,所以如果你心情还比较高兴,也是可以扫码打赏博主,哈哈哈(っ•̀ω•́)っ✎⁾⁾!

  • 相关阅读:
    20162325 金立清 S2 W7 C16
    2017-2018-1 我爱学Java 第三周 作业
    Android演示Stack(课下作业)
    20162325 金立清 S2 W6 C15
    YanghuiTriangle
    20162327WJH第一次实验——线性结构
    20162327 《程序设计与数据结构》第三周学习总结
    20162327《程序设计与数据结构》第一周作业
    20162327WJH 实验三 《敏捷开发与XP实践》 实验报告
    20162328WJH实验五网络编程与安全实验报告
  • 原文地址:https://www.cnblogs.com/mrluo735/p/15780593.html
Copyright © 2011-2022 走看看