位运算的好用技巧 2025-07-01

位运算种类

(1) 逻辑运算(按位操作)

  • 与(&:对应位均为 1 时结果为 1,否则为 0
    5 & 3 → 0101 & 0011 = 0001 (十进制1)
    
  • 或(|:对应位至少一个为 1 时结果为 1
    5 | 3 → 0101 | 0011 = 0111 (十进制7)
    
  • 异或(^:对应位不同时结果为 1
    5 ^ 3 → 0101 ^ 0011 = 0110 (十进制6)
    
  • 取反(~:所有位翻转(0110)。
    ~5 → ~0101 = 1010(假设4位,十进制-6,补码表示)
    

(2) 移位运算

  • 左移(<<:所有位向左移动,低位补 0
    5 << 1 → 0101 << 1 = 1010 (十进制10,相当于乘2)
    
  • 右移(>>:所有位向右移动,高位补符号位(算术右移)或补 0(逻辑右移)。
    -5 >> 1 → 11111011 >> 1 = 11111101(算术右移,结果仍为负数)
    

左移都是等价于逻辑左移
对于有符号数来说,右移默认是算术右移。

#include <iostream>
using namespace std;

int main() {
    // 无符号数:逻辑右移
    unsigned int a = 0b10000000; // 128
    cout << (a >> 2) << endl;   // 结果 32 (0b00100000)

    // 有符号数:通常是算术右移
    int b = -8; // 二进制补码:111...1111000
    cout << (b >> 1) << endl;    // 结果 -4 (111...1111100)

    // 强制逻辑右移(通过转为无符号)
    cout << ((unsigned)b >> 1) << endl; // 结果 2147483644 (0b011...1111100)
    return 0;
}

表格版

位运算所有符号表示及英文缩写

运算名称 符号 英文全称 缩写 示例 说明
按位与(AND) & Bitwise AND AND a & b 对应位均为 1 时结果为 1
按位或(OR) ` ` Bitwise OR OR `a b` 对应位至少一个为 1 时结果为 1
按位异或(XOR) ^ Bitwise XOR XOR a ^ b 对应位不同时结果为 1
按位取反(NOT) ~ Bitwise NOT NOT ~a 所有位取反(0→1,1→0)
左移(Shift Left) << Left Shift SHL a << n 左移 n 位,低位补 0
算术右移 >> Arithmetic Right Shift SAR a >> n 右移 n 位,高位补符号位(带符号)
逻辑右移 >>> Logical Right Shift SHR a >>> n 右移 n 位,高位补 0(无符号)
循环左移 Rotate Left ROL 无标准符号 左移时溢出的位补到低位
循环右移 Rotate Right ROR 无标准符号 右移时溢出的位补到高位

说明:

  1. 循环移位(ROL/ROR) 在部分 CPU 指令或语言库中有提供,但无统一符号,通常用函数实现(如 _rotl_rotr)。
  2. 逻辑右移(>>> 仅在某些语言(如 Java、JavaScript)中支持,C/C++ 无此运算符。
  3. 算术右移(>> 在 C/C++ 等语言中对有符号整数生效,保持符号位不变。

取反、补码运算

int a = 5;  // 原码:00000101,补码:00000101
int b = ~a; // 按位取反:11111010(补码)
int c = -3; // 原码:10000011,补码:11111101
int d = ~c; // 按位取反:00000010(补码)
int x = 6;  // 补码:00000110
int y = -x; // 取负:11111010(补码)
int z = -4; // 补码:11111100
int w = -z; // 取负:00000100(补码)

位运算的好用技巧

位运算的核心本质就是直接利用二进制的特性进行操作!

判断奇偶

在二进制中,如果是奇数最后一位一定是1

if ((n & 1) == 0) {
    cout << "偶数" << endl;
} else {
    cout << "奇数" << endl;
}

清除最低位的1

n&(n-1);

建立清除最低位的1,延申出的功能

计算一个数的二进制中1的数量

int bitCount(int n)
{
  int count=0;
  while(n>0) 
  {
    n&=(n-1);
    count++;
  }
  return count;
}

检查是否是2的幂

if(n>0&&(n&(n-1)==0))
{
  就是2的倍数了
}

是不是4的幂

[4的幂]https://leetcode.cn/problems/power-of-four/description/

bool isPowerOfFour(int n) 
{ return n > 0 && (n & (n - 1)) == 0 && (n & 0xaaaaaaaa) == 0; } 
bool isPowerOfFour(int n) {
        return n > 0 && (n & (n - 1)) == 0 && n % 3 == 1;
    }

快速判断符号是否相同

bool func(int a,int b)
{
  if((a^b)>=0)
    {return true;}
  else
  {return false;}
}

提取最右侧的1

int rightmost_one = n & -n;

快速乘/除2的幂

n<<1;//n*2
n>>1;//n/2

掩码操作

// 获取低4位
int low_4_bits = n & 0xF;

// 设置第3位为1
n |= (1 << 2);

// 清除第5位为0
n &= ~(1 << 4);

循环移位(32位整数)

// 左移k位
n = (n << k) | (n >> (32 - k));

// 右移k位
n = (n >> k) | (n << (32 - k));

向上取整到最近的2的幂

unsigned int next_power_of_two(unsigned int n) {
    n--;
    n |= n >> 1;
    n |= n >> 2;
    n |= n >> 4;
    n |= n >> 8;
    n |= n >> 16;
    return n + 1;
}

取绝对值 (不实用)

等价于std::abs
在计算机中存储的是补码(对于正数来说,原码补码反码是一样的)

//如果是负数,要记得n是补码 mask=11...1,打印的话显示mask=-1
int mask=n>>31; //符号掩码(负数全1,正数全0) 因为遵守算术运算 
//对于正数无影响 mask就是全0 
int abs_n=(n^mask)-mask;//等价于(n+mask)^mask

对于计算机的负数取绝对值运算来说,

使用逐位检查一个具体的int变量需要多少个二进制位表示

应用前提:变量是大于0的数(正数)

交换两个数(不推荐使用,当两个数的地址是一个的时候会出错,这个更推荐使用std::swap())

a ^= b;
b ^= a;
a ^= b;
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 概述 在学习位运算之前,先说下几个概念: 机器数:一个数字在计算机中的二进制表达形式就叫做机器数。机器数是有符号位...
    骑着乌龟去看海阅读 2,476评论 1 4
  • 首先我们需要知道:源码、反码、补码,并且知道2进制最高位是符号位0代表正数,1代表负数。 正数: 正数的反码,补码...
    D_R_M阅读 956评论 0 0
  • 位运算 算法 -1.与: &或: |非: !异或 : ^ 相同为 0, 不同为 1int 32 位 -> int ...
    YOLO哈哈哈阅读 880评论 0 0
  • 一:进制 在计算机编程中,整数可以通过二进制,八进制,十进制,十六进制 十进制可通过方程转二、八、十六进制。倒转需...
    生命的怒放阅读 615评论 0 0
  • iOS位运算 一、二进制 1、什么是二进制 二进制(binary),发现者莱布尼茨[https://baike.b...
    9527abc阅读 216评论 0 0