.
博客主页:倔强的石头的CSDN主页
Gitee主页:倔强的石头的gitee主页
⏩ 文章专栏:《C++指南》
期待您的关注![]()
在C++编程中,位运算是一种直接对二进制位进行操作的运算方式。它不仅可以提高程序的运行效率,还能解决一些特定的算法问题,如“只出现一次的数字”系列题目。
下面将详细介绍C++位运算的相关知识,包括位运算符的使用、规则以及实战使用技巧。
C++ 提供了六种位运算符,分别是按位与(&
)、按位或(|
)、按位异或(^
)、按位取反(~
)、左移(<<
)和右移(>>
)。下面将分别介绍这些运算符的使用和规则。
&
)1
时,结果位才为 1
,否则为 0
。#include
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
的二进制表示为 0101
,b
的二进制表示为 0011
。按位与运算时,逐位进行比较,只有第四位(从右往左数)两个操作数都为 1
,所以结果的二进制表示为 0001
,十进制为 1
。|
)1
,结果位就为 1
,只有当两个对应位都为 0
时,结果位才为 0
。#include
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
的二进制表示为 0101
,b
的二进制表示为 0011
。按位或运算时,逐位比较,只要有一个位为 1
,结果位就为 1
,所以结果的二进制表示为 0111
,十进制为 7
。^
)1
,相同时结果位为 0
。#include
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
的二进制表示为 0101
,b
的二进制表示为 0011
。按位异或运算时,逐位比较,不同位为 1
,相同位为 0
,所以结果的二进制表示为 0110
,十进制为 6
。~
)1
变为 0
,0
变为 1
。#include
int main() {
int a = 5; // 二进制表示: 0101
int result = ~a; // 二进制结果: 1010(补码表示),十进制取决于具体的编译器和机器
std::cout << "~a = " << result << std::endl;
return 0;
}
a
的二进制表示为 0101
,按位取反后为 1010
。在计算机中,整数通常以补码形式存储,所以 ~a
的实际十进制值取决于具体的编译器和机器。<<
)0
填充。左移 n
位相当于将操作数乘以 2
的 n
次方。#include
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
。>>
)0
填充;对于有符号数,左边空出的位用符号位(正数为 0
,负数为 1
)填充。右移 n
位相当于将操作数除以 2
的 n
次方。#include
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
,则该数为奇数;如果最低位为 0
,则该数为偶数。
#include
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;
}
可以使用按位异或运算交换两个数的值,而不需要使用额外的临时变量。
#include
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;
}
在“只出现一次的数字”系列题目中,利用按位异或运算的特性可以高效地找出只出现一次的数字。例如,在一个数组中,除了一个元素只出现一次,其余元素都出现两次,通过对数组中所有元素进行异或运算,最终结果就是只出现一次的元素。
#include
#include
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++指南】“单身狗问题”——只出现一次的数字 系列问题
1
的个数可以使用按位与运算和右移运算来计算一个数的二进制表示中 1
的个数。
#include
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++ 中一种强大而高效的运算方式,通过对二进制位的直接操作,可以解决许多复杂的问题。
在实际编程中,合理运用位运算符可以提高程序的性能和效率。
需要注意的是,位运算的结果通常依赖于具体的编译器和机器,特别是在处理有符号数的右移操作时,要考虑符号位的影响。
同时,位运算的代码可能会比较难以理解和调试,因此在使用时要谨慎,并添加必要的注释
。