今天喵博主介绍一下位操作符,先讲知识,然后通过题来运用位操作符。
目录
内容1: "~"
内容2:''^''、 "&"、 "|"
内容3:按位异或:'' ^ ''、按位与"&"的秘密
内容4:做题运用
内容1: "~" :
//~ 对一个数的二进制按位取反(补码按位取反)
//整数在内存中存储的时候,存储是二进制
//一个整数的二进制表示有3种形式:
//原码
//反码
//补码
//正的整数:原码、反码、补码相同
//负的整数:原码、反码、补码是计算的
//有符号的整数,最高位是0,表示正数
//最高位是1,表示负数
//正的整数
int a = 1;//4个字节 - 32bit
00000000000000000000000000000001 - 原码
00000000000000000000000000000001 - 反码
00000000000000000000000000000001 - 补码
//负的整数
int a = -1
10000000000000000000000000000001 - 原码
11111111111111111111111111111110 - 反码(原码的符号位不变,其他位按位取反得到反码)
11111111111111111111111111111111 - 补码(反码的二进制序列+1就是补码)
//内存中存储整数的时候,存储的是二进制的补码
//计算的时候采用也是补码 (重点)
int main()
{
int a = 0;
printf("%d\n", ~a);//-1
//00000000000000000000000000000000 - 原码(0是整数)
//00000000000000000000000000000000 - 补码
//11111111111111111111111111111111 - 按位取反(补码)
//11111111111111111111111111111110 - 反码
//10000000000000000000000000000001 - 原码//-1
return 0;
}
内容2:''^''、 "&"、 "|" :
// 位操作符
// & - 按二进制位与
// ^ - 按二进制位异或
// | - 按二进制位或
int main()
{
int a = 3;
int b = 5;
//
//int c = a & b;//1
//按位与 有0就为0
//000000000 000000000 00000000 00000011//3的补码
//000000000 000000000 00000000 00000101//5的补码(注意:正的整数原反补相同哦)
//000000000 000000000 00000000 00000001 //3 & 5 = 1
//printf("%d\n", c);//c = 1
//按位异或 - 相同为0,相异为1
//int d = a ^ b;//6
//000000000 000000000 00000000 00000011
//000000000 000000000 00000000 00000101
//000000000 000000000 00000000 00000110 //6
//printf("%d\n", d);
//按位或 有1就为1
int e = a | b;//7
//000000000 000000000 00000000 00000011
//000000000 000000000 00000000 00000101
//000000000 000000000 00000000 00000111 //7
printf("%d\n", e);
return 0;
}
内容3:按位异或:'' ^ ''、按位与"&"的秘密:
(1)按位异或:'' ^ ''的秘密:
1.'' ^ '':逐比特位,相同为0,不同为1
2.'' ^ '':支持结合律和交换律
3.任何数和0异或都是它本身,任何数和它本身异或都是0
(2)按位与"&"的秘密:
1.n & (n-1) 消 1
2.如果是2的次方:n & (n-1)=0
内容4:"^"运用
1.
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
限制:
2 <= nums.length <= 10000
来源:
力扣https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* singleNumbers(int* nums, int numsSize, int* returnSize){
int i = 0;
int sum = 0;
int logal=0;
int* ret=(int*)malloc(sizeof(int)*2);
ret[0]=ret[1]=0;
//1.先异或整个数组得到了两个不同数字的异或值sum
for(i = 0 ;i < numsSize ;i++)
{
sum^=nums[i];
}
//2.找出二进制上为1的位数需要右移几次(划分组)
for(i = 0;i < 32;i++)
{
if((sum>>i)&1==1)
{
logal=i;
break;
}
}
//将数组按照logal位不同区分出两组数,这两组数分别有一个单独出现
for(i = 0 ;i < numsSize ;i++)
{
if((nums[i]>>logal)&1==1)
{
ret[0]^=nums[i];
}
else
{
ret[1]^=nums[i];
}
}
* returnSize=2;
return ret;
}
详细讲解:
2.统计二进制中1的个数
写一个函数返回参数二进制中 1 的个数。#include<stdio.h> size_t count_bit( int n) { int count = 0; while (n) { n = n & (n - 1); count++; } return count; } int main() { int num = 0; scanf("%d", &num); size_t ret = count_bit(num); printf("%d\n", ret); return 0; }
3.写一个代码,判断一个数是不是2的次方数
#include<stdio.h> int main() { int n = 0; scanf("%d", &n); if ((n & (n - 1)) == 0) { printf("YES!\n"); } else { printf("NO!\n"); } return 0; }