喵呜,来啦来啦:‘‘~‘‘、位操作符‘‘^‘‘、“&“、“|“的运用

(24) 2024-04-16 17:01:01

今天喵博主介绍一下位操作符,先讲知识,然后通过题来运用位操作符。

目录

内容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.'' ^ '':支持结合律和交换律

喵呜,来啦来啦:‘‘~‘‘、位操作符‘‘^‘‘、“&“、“|“的运用 (https://mushiming.com/)  第1张

3.任何数和0异或都是它本身,任何数和它本身异或都是0

喵呜,来啦来啦:‘‘~‘‘、位操作符‘‘^‘‘、“&“、“|“的运用 (https://mushiming.com/)  第2张

2)按位与"&"的秘密:

1.n & (n-1)  消 1

喵呜,来啦来啦:‘‘~‘‘、位操作符‘‘^‘‘、“&“、“|“的运用 (https://mushiming.com/)  第3张

 2.如果是2的次方:n & (n-1)=0

喵呜,来啦来啦:‘‘~‘‘、位操作符‘‘^‘‘、“&“、“|“的运用 (https://mushiming.com/)  第4张

内容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;


}

详细讲解:

喵呜,来啦来啦:‘‘~‘‘、位操作符‘‘^‘‘、“&“、“|“的运用 (https://mushiming.com/)  第5张

 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;
}

THE END

发表回复