【C++指南】位运算知识详解

.
💓 博客主页:倔强的石头的CSDN主页
📝Gitee主页:倔强的石头的gitee主页
⏩ 文章专栏:《C++指南》
期待您的关注

文章目录

  • 引言
    • 一、位运算符概述
        1. 按位与(`&`)
        1. 按位或(`|`)
        1. 按位异或(`^`)
        1. 按位取反(`~`)
        1. 左移(`<<`)
        1. 右移(`>>`)
    • 二、位运算的实战使用技巧
        1. 判断奇偶性
        1. 交换两个数的值
        1. 找出只出现一次的数字
        1. 计算一个数的二进制表示中 `1` 的个数
    • 三、总结

引言

在C++编程中,位运算是一种直接对二进制位进行操作的运算方式。它不仅可以提高程序的运行效率,还能解决一些特定的算法问题,如"只出现一次的数字"系列题目。

下面将详细介绍C++位运算的相关知识,包括位运算符的使用、规则以及实战使用技巧。

一、位运算符概述

C++ 提供了六种位运算符,分别是按位与(&)、按位或(|)、按位异或(^)、按位取反(~)、左移(<<)和右移(>>)。下面将分别介绍这些运算符的使用和规则。

1. 按位与(&

  • 规则 :对两个操作数的对应二进制位进行与运算,只有当两个对应位都为 1 时,结果位才为 1,否则为 0
  • 示例代码
cpp 复制代码
#include <iostream>
int main() {
    int a = 5; // 二进制表示: 0101
    int b = 3; // 二进制表示: 0011
    int result = a & b; // 二进制结果: 0001,十进制为 1
    std::cout << "a & b = " << result << std::endl;
    return 0;
}
  • 解释 :在上述代码中,a 的二进制表示为 0101b 的二进制表示为 0011。按位与运算时,逐位进行比较,只有第四位(从右往左数)两个操作数都为 1,所以结果的二进制表示为 0001,十进制为 1

2. 按位或(|

  • 规则 :对两个操作数的对应二进制位进行或运算,只要两个对应位中有一个为 1,结果位就为 1,只有当两个对应位都为 0 时,结果位才为 0
  • 示例代码
cpp 复制代码
#include <iostream>
int main() {
    int a = 5; // 二进制表示: 0101
    int b = 3; // 二进制表示: 0011
    int result = a | b; // 二进制结果: 0111,十进制为 7
    std::cout << "a | b = " << result << std::endl;
    return 0;
}
  • 解释a 的二进制表示为 0101b 的二进制表示为 0011。按位或运算时,逐位比较,只要有一个位为 1,结果位就为 1,所以结果的二进制表示为 0111,十进制为 7

3. 按位异或(^

  • 规则 :对两个操作数的对应二进制位进行异或运算,当两个对应位不同时,结果位为 1,相同时结果位为 0
  • 示例代码
cpp 复制代码
#include <iostream>
int main() {
    int a = 5; // 二进制表示: 0101
    int b = 3; // 二进制表示: 0011
    int result = a ^ b; // 二进制结果: 0110,十进制为 6
    std::cout << "a ^ b = " << result << std::endl;
    return 0;
}
  • 解释a 的二进制表示为 0101b 的二进制表示为 0011。按位异或运算时,逐位比较,不同位为 1,相同位为 0,所以结果的二进制表示为 0110,十进制为 6

4. 按位取反(~

  • 规则 :对操作数的每一个二进制位进行取反操作,即 1 变为 00 变为 1
  • 示例代码
cpp 复制代码
#include <iostream>
int main() {
    int a = 5; // 二进制表示: 0101
    int result = ~a; // 二进制结果: 1010(补码表示),十进制取决于具体的编译器和机器
    std::cout << "~a = " << result << std::endl;
    return 0;
}
  • 解释a 的二进制表示为 0101,按位取反后为 1010。在计算机中,整数通常以补码形式存储,所以 ~a 的实际十进制值取决于具体的编译器和机器。

5. 左移(<<

  • 规则 :将操作数的二进制位向左移动指定的位数,右边空出的位用 0 填充。左移 n 位相当于将操作数乘以 2n 次方。
  • 示例代码
cpp 复制代码
#include <iostream>
int main() {
    int a = 5; // 二进制表示: 0101
    int result = a << 2; // 二进制结果: 010100,十进制为 20
    std::cout << "a << 2 = " << result << std::endl;
    return 0;
}
  • 解释a 的二进制表示为 0101,左移 2 位后,右边空出的两位用 0 填充,得到 010100,十进制为 20,相当于 5 * 2^2

6. 右移(>>

  • 规则 :将操作数的二进制位向右移动指定的位数。对于无符号数,左边空出的位用 0 填充;对于有符号数,左边空出的位用符号位(正数为 0,负数为 1)填充。右移 n 位相当于将操作数除以 2n 次方。
  • 示例代码
cpp 复制代码
#include <iostream>
int main() {
    int a = 5; // 二进制表示: 0101
    int result = a >> 1; // 二进制结果: 0010,十进制为 2
    std::cout << "a >> 1 = " << result << std::endl;
    return 0;
}
  • 解释a 的二进制表示为 0101,右移 1 位后,左边空出的位用 0 填充,得到 0010,十进制为 2,相当于 5 / 2

二、位运算的实战使用技巧

1. 判断奇偶性

可以使用按位与运算判断一个整数的奇偶性。如果一个数的二进制表示的最低位为 1,则该数为奇数;如果最低位为 0,则该数为偶数。

cpp 复制代码
#include <iostream>
bool isOdd(int num) {
    return (num & 1) == 1;
}
int main() {
    int num = 5;
    if (isOdd(num)) {
        std::cout << num << " is odd." << std::endl;
    } else {
        std::cout << num << " is even." << std::endl;
    }
    return 0;
}

2. 交换两个数的值

可以使用按位异或运算交换两个数的值,而不需要使用额外的临时变量。

cpp 复制代码
#include <iostream>
void swap(int& a, int& b) {
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}
int main() {
    int a = 5;
    int b = 3;
    std::cout << "Before swap: a = " << a << ", b = " << b << std::endl;
    swap(a, b);
    std::cout << "After swap: a = " << a << ", b = " << b << std::endl;
    return 0;
}

3. 找出只出现一次的数字

在"只出现一次的数字"系列题目中,利用按位异或运算的特性可以高效地找出只出现一次的数字。例如,在一个数组中,除了一个元素只出现一次,其余元素都出现两次,通过对数组中所有元素进行异或运算,最终结果就是只出现一次的元素。

cpp 复制代码
#include <iostream>
#include <vector>
int singleNumber(std::vector<int>& nums) {
    int result = 0;
    for (int num : nums) {
        result ^= num;
    }
    return result;
}
int main() {
    std::vector<int> nums = {1, 2, 2, 3, 3};
    int single = singleNumber(nums);
    std::cout << "The single number is: " << single << std::endl;
    return 0;
}

关于该问题的更多实践可参考文章:
【C++指南】"单身狗问题"------只出现一次的数字 系列问题

4. 计算一个数的二进制表示中 1 的个数

可以使用按位与运算和右移运算来计算一个数的二进制表示中 1 的个数。

cpp 复制代码
#include <iostream>
int countOnes(int num) {
    int count = 0;
    while (num) {
        count += num & 1;
        num >>= 1;
    }
    return count;
}
int main() {
    int num = 5;
    int onesCount = countOnes(num);
    std::cout << "The number of 1s in the binary representation of " << num << " is: " << onesCount << std::endl;
    return 0;
}

三、总结

位运算是 C++ 中一种强大而高效的运算方式,通过对二进制位的直接操作,可以解决许多复杂的问题。

在实际编程中,合理运用位运算符可以提高程序的性能和效率。

需要注意的是,位运算的结果通常依赖于具体的编译器和机器,特别是在处理有符号数的右移操作时,要考虑符号位的影响。

同时,位运算的代码可能会比较难以理解和调试,因此在使用时要谨慎,并添加必要的注释

相关推荐
猷咪7 分钟前
C++基础
开发语言·c++
IT·小灰灰8 分钟前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧10 分钟前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q11 分钟前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳011 分钟前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾11 分钟前
php 对接deepseek
android·开发语言·php
CSDN_RTKLIB14 分钟前
WideCharToMultiByte与T2A
c++
vx_BS8133015 分钟前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计
2601_9498683615 分钟前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
星火开发设计29 分钟前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识