二进制位运算题

news2024/9/26 1:18:11

在这里插入图片描述

本期介绍🍖
主要介绍:1. 在不创建临时变量的情况下交换两个变量,2. 计算变量在内存中存放2进制位“1”的个数,3. 求两个数的二进制中不同位的个数,4. 分别打印整数的二进制中奇数位和偶数位,5. 判断一个整数是不是2的n次方,6. 在成对元素的数组中找单身狗。


文章目录

  • 1. 交换两个变量(不创建临时变量)
    • 1.1 加减法
    • 1.2 异或法
  • 2. 计算变量在内存中存放2进制位“1”的个数
    • 2.1 除二取余法
    • 2.2 移位与1法
    • 2.3 消1计数法
  • 3. 求两个数二进制中不同位的个数
  • 4. 打印整数二进制的奇数位和偶数位
  • 5. 判断一个整数是不是2的n次方
  • 6. 在成对元素的数组中找单身狗
    • 6.1 题目1
    • 6.2 题目2


1. 交换两个变量(不创建临时变量)

  题目: 交换两个整数的内容,在交换的过程中不允许创建第三个临时变量。
  一般想要交换两个变量,会通过创建第三个临时变量来完成,就如同想要将两瓶饮料进行交换,需要第三个空瓶一样。代码实现如下所示:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	int tmp = 0;
	printf("交换前:a=%d, b=%d\n", a, b);
	//交换变量a和变量b
	tmp = a;
	a = b;
	b = tmp;
	printf("交换后:a=%d, b=%d\n", a, b);
	return 0;
}

在这里插入图片描述


1.1 加减法

  解题思路: 求出两个变量的和,通过和与变量的差,在不创建第三个临时变量的情况下交换两个变量。代码如下所示:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	printf("交换前:a=%d, b=%d\n", a, b);
	//交换变量a和变量b
	a = a + b;
	b = a - b;
	a = a - b;
	printf("交换后:a=%d, b=%d\n", a, b);
	return 0;
}

在这里插入图片描述

  其实不难看出加减法是存在缺陷的,当a和b的值都很大的时候(即都非常接近int类型所能表示范围中的最大值),那么a+b的值必然会超过int型所能存放的极限,导致一些二进制位的丢失,最后交换的结果必然会是错误的。


1.2 异或法

  所谓的异或法就是通过异或操作符符 “ ^ ” 来实现交换两变量中的值。在这里不得不说一下异或运算符的一些性质:

  性质1: 计算3 ^ 3表达式,3的二进制位为011,那两个同为011的二进制位进行异或操作,结果必然会是000;同理5 ^ 5的结果也是000,所以不难看出异或的第一条性质为:x^x = 0

  性质2: 计算3 ^ 0表达式,3的二进制位为011,0的二进制位为000,进行异或操作结果为011,也为3。由此发现不管什么数与0进行异或结果必然会是该数本身,所以异或的第二条性质为:x^0=a

  性质3: 表达式(3 ^ 3 ^ 5)的计算结果为5,表达式(3 ^ 5 ^ 3)的结果也为5。所以不难看出异或的第三条性质(交换律):(x ^ x ^ y) = (x ^ y ^ x)

  代码实现如下所示:

#include<stdio.h>
int main()
{
	int a = 10;
	int b = 20;
	printf("交换前:a=%d, b=%d\n", a, b);
	//交换变量a和变量b
	a = a ^ b;//a里面存放a^b
	b = a ^ b;//此时的a^b其实是(a^b)^b,结果为a
	a = a ^ b;//此时的a为a^b,b为a,故a^b其实是(a^b)^a,结果为b
	printf("交换后:a=%d, b=%d\n", a, b);
	return 0;
}

在这里插入图片描述

  其实可以将a^b得到的结果看作是一个秘盒,a与b通过异或与秘盒结合都可以得到另个数。异或法就没有加减法的缺陷,不会因数据过大使得存储不下。


2. 计算变量在内存中存放2进制位“1”的个数

  题目:输入一个整数 n ,计算n在内存中存放的二进制位中1的个数(其中负数用补码表示)。下面会用3种不同的方法来解决这道笔试题。


2.1 除二取余法

  在数学中要将十进制数转换成二进制数老师肯定教过一种方法“ 除2取余法 ”。举例如下图所示,计算十进制89化为二进制数。除完所有数,把所有余数从下往上排序后,得到的结果就是89的二进制表示形式为:1011001。
在这里插入图片描述
  引用此法,每次除2后统计余数为1的情况,这样就可以做到计算变量在内存中存放2进制位为“1”的个数啦。代码如下:

#include<stdio.h>
int sta_bit_num(int n)
{
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
		{
			count++;
		}
		n /= 2;
	}
	return count;
}
int main()
{
	int n = 0;
	int count = 0;
	printf("请输入要计算的数:");
	scanf("%d", &n);
	count = sta_bit_num(n);
	printf("二进制中1的个数:%d\n", count);
}

在这里插入图片描述
  乍一看似乎没什么问题,但当输入负数时就会发生错误。就譬如输入-1。如下图所示,得出的结果为0,如下图所示:

在这里插入图片描述

  由于在编写代码时,压根就没有思考过负数的情况。而负数再内中存放的补码的形式与正数是不同的,所以如果还按照原先计算正数的除2取余法来计算负数必然错误。解决方法:将输入的有符号数强制类型转换为无符号数,用除2取余法再对该无符号数进行统计就间接达到效果了。代码如下:

#include<stdio.h>
int sta_bit_num(unsigned int n)
{
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
		{
			count++;
		}
		n /= 2;
	}
	return count;
}
int main()
{
	int n = 0;
	int count = 0;
	printf("请输入要计算的数:");
	scanf("%d", &n); 
	count = sta_bit_num(n);
	printf("二进制中1的个数:%d\n", count);
}

在这里插入图片描述


2.2 移位与1法

  解题思路:一个数只要" &1 "就可以求得该数在内存中存放的二进制位的最低位,再通右移操作符“ >> ”就可以统计32位上所有1的个数了。如下图所示:

在这里插入图片描述
  代码如下:

#include<stdio.h>
int sta_bit_num(int n)
{
	int count = 0;
	int i = 0;
	for (i = 0; i < 32; i++)
	{
		if ((n >> i) & 1 == 1)
		{
			count++;
		}
	}
	return count;
}
int main()
{
	int n = 0;
	int count = 0;
	printf("请输入要计算的数:");
	scanf("%d", &n);
	count = sta_bit_num(n);
	printf("二进制中1的个数:%d\n", count);
}

在这里插入图片描述

  值得注意,移位与1法会做多余的判断,不管被求的那个数在内存中的二进制位有几个1,始终都是要循环判断32次的。


2.3 消1计数法

  根据题意可知,所需统计的仅仅只是二进制位中1的个数,但上面两种方法在判断统计二进制位1的同时还会多余的判断二进制位0。
  现在讲解一种非常牛逼的算法“ 消1计数法 ”。该方法是将被求的数" & "比被求数小1的数,即:n & (n-1) 。计算结果会让二进制序列中最低位的那个1变为0。如果再多来几次这样的操作,被求的那个数最终会变成0,这样做就效率不就上来了嘛。如下图所示:
在这里插入图片描述
  代码为:

#include<stdio.h>
int sta_bit_num(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}
int main()
{
	int n = 0;
	int count = 0;
	printf("请输入要计算的数:");
	scanf("%d", &n);
	count = sta_bit_num(n);
	printf("二进制中1的个数:%d\n", count);
}

在这里插入图片描述
在这里插入图片描述


3. 求两个数二进制中不同位的个数

  题目: 求两个整数m和n的二进制序列中,有多少位不相同的?输入例子:1999 , 2299;输出例子:7。
  大家在没看过上面的算法思路时,来求解这道题目的思路一定是逐位进行比较的是否相等,效率太低。现在再思考一下这道题的解法,只需要两步:

  第1步:按位异或^计算两个数的相异处。

  第2步:用“ 消1计数法 ”统计二进制位中1的个数,即:二进制位相异处的个数。

  代码如下:

#include<stdio.h>
int sta_bit_num(int x, int y)
{
	int count = 0;
	int n = x ^ y;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}
int main()
{
	int a = 0;
	int b = 0;
	int count = 0;
	printf("请输入要计算的两个数:");
	scanf("%d%d", &a, &b);
	count = sta_bit_num(a, b);
	printf("两个数二进制数中不同位的个数:%d\n", count);
}

在这里插入图片描述


4. 打印整数二进制的奇数位和偶数位

  题目: 获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列。
  该题先假设二进制序列中最低位为奇数位1,然后我们想办法从高位向低位打印奇数位、偶数位。这样就需要两个循环分别打印奇数位和偶数位了。

#include<stdio.h>
void print_odd(unsigned int n)
{
	int i = 0;
	printf("打印奇数位:\n");
	for (i = 30; i >= 0; i -= 2)
	{
		printf("%d ", (n >> i) & 1);
	}
	printf("\n");
}
void print_even(int n)
{
	int i = 0;
	printf("打印偶数位:\n");
	for (i = 31; i >= 1; i -= 2)
	{
		printf("%d ", (n >> i) & 1);
	}
	printf("\n");
}
int main()
{
	int n = 0;
	printf("请输入一个数:");
	scanf("%d", &n);
	print_odd(n);
	print_even(n);
	return 0;
}

在这里插入图片描述
在这里插入图片描述


5. 判断一个整数是不是2的n次方

  解题思路:由于整数 2n 的二进制序列只可能存在一个1。所以在求一个数是否为2 ^ n的整数时,只需要判断该数的二进制序列中只存在一个1就可以了。那这里不想也知道用消1计数法最为高效。代码如下:

#include<stdio.h>
int is_pow(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
	
}
int main()
{
	int n = 0;
	printf("请输入一个数:");
	scanf("%d", &n);
	if (is_pow(n) == 1)
	{
		printf("整数%d是2的n次方\n", n);
	}
	else
	{
		printf("整数%d不是2的n次方\n", n);
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述


6. 在成对元素的数组中找单身狗

6.1 题目1

  题目:{1,2,3,4,5,4,3,2,1}的一组整型数组中,只有一个数出现一次,其他数都是成对出现的,请找出那个只出现过一次的数字。
  解题思路:异或操作符有两个个性质x^x = 0x^0 = x,由于这一组数中只有一个数出现一次,其余数都是成对出现的,将所有数都异或在一起,就可以得到那个单身狗了。实现代码如下:

#include<stdio.h>
int find_once(int arr[], int sz)
{
	int i = 0;
	int tmp = 0;
	for (i = 0; i < sz; i++)
	{
		tmp = tmp ^ arr[i];
	}
	return tmp;
}
int main()
{
	int arr[] = { 1,2,3,4,5,4,3,2,1 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int result = find_once(arr, sz);
	printf("那个单身狗是:%d\n", result);
	return 0;
}

在这里插入图片描述


6.2 题目2

  题目:{1,2,3,4,5,4,3,2,1,6}的一组整型数组中,有两个数出现一次,其他数都是成对出现的,请找出那两个只出现过一次的数字。
  解题思路:异或操作符有两个个性质x^x = 0x^0 = x,由于这一组数中有两个数只出现一次,其余数都是成对出现的。可以找这两个数的区别,然后将这一组数分成两组,各占一个单身狗。最后分别将两组数异或在一起,就可以得到那两个单身狗了。实现代码如下:

#include<stdio.h>
void find_once(int arr[], int sz, int* pa, int* pb)
{
	//1.找两个单身狗的差异
	int diff = 0;
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		diff = diff ^ arr[i];
	}
	//2.确定差异的二进制位
	int pos = 0;
	for (i = 0; i < 32; i++)
	{
		if ((diff & 1) == 1)
		{
			pos = i;
			break;
		}
		diff = diff >> 1;
	}
	//3.按差异分组并将异或后的结果返回
	for (i = 0; i < sz; i++)
	{
		if ((arr[i] >> pos) & 1 == 1)
			*pa ^= arr[i];
		else
			*pb ^= arr[i];
	}
}
int main()
{
	int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int a = 0;
	int b = 0;
	find_once(arr, sz, &a, &b);
	printf("找到了单身狗:%d,%d\n", a, b);
	return 0;
}

在这里插入图片描述


在这里插入图片描述

这份博客👍如果对你有帮助,给博主一个免费的点赞以示鼓励欢迎各位🔎点赞👍评论收藏⭐️,谢谢!!!
如果有什么疑问或不同的见解,欢迎评论区留言欧👀。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2165352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SentencePiece进行文本分类

SentencePieces 前言 Step1:故事 SentencePiece 是一个无监督的文本分词器和 detokenizer(还原回去的&#xff1f;)主要用于词汇表大小是预定的文本生成系统中它拓展了原始句子的训练&#xff0c;实现子词单元如 BPE 和 unigram language model技术亮点 纯数据驱动&#xff…

Qemu开发ARM篇-6、emmc/SD卡AB分区镜像制作

文章目录 1、AB分区镜像制作2、uboot修改3、镜像启动 在上一篇 Qemu开发ARM篇-5、buildroot制作根文件系统并挂载启动中&#xff0c;我们通过buildroot制作了根文件系统&#xff0c;并通过 SD卡的形式将其挂载到设备并成功进行了启动&#xff0c;但上一章中&#xff0c;我们的…

车载应用的多功能需求与公安、金融等行业的应用特点

随着科技的快速发展&#xff0c;车载应用的功能需求也日益多样化。除了基本的视频监控功能外&#xff0c;现代车载应用还需满足一系列高级功能&#xff0c;如无线网络视频监控、GPS卫星定位、车辆调度、语音报站、行驶信息记录以及多媒体娱乐广告播放等。这些功能在公安、金融等…

2024年数字化转型与管理国际学术会议(DTM 2024)

目录 重要信息 大会简介 大会组委 征稿主题 论文出版 会议议程 参会方式 重要信息 大会官网&#xff1a;www.icemme.org&#xff08;点击了解大会&#xff0c;投稿等详细信息&#xff09; 大会时间&#xff1a;2024年11月22-24日 大会地点&#xff1a;中国-大连 大会…

三维重建的几何评价指标

1.三维重建的几何评价指标 1.1 Chamfer Distance Geometry quality (1) Chamfer Distance&#xff08;CD&#xff09; CD衡量两组点云之间的几何差异&#xff0c;距离越小越好。 CD是一种用于衡量两个点云之间相似度的常用几何评价指标。它计算一个点云中每个点到另一个点云的…

Qt5.15和Qt6.7配置Android开发环境

最近重新安装了Qt5.15.2和Qt6.7.2,使用Qt Creator14.0.1,配置Android开发环境时又碰到了一些问题,记录如下。 1、Qt6.7.2使用AndroidStudio的JDK 因为系统原来安装了AndroidStudio2024,系统自动检测了JDK位置,点击设置SDK,可以自动安装好相应的NDK。 打开Qt Creator14…

JavaEE——多线程的状态及线程安全问题

目录 一、线程的状态 1、NEW 2、 TERMINATED 3、RUNNABLE 4、TIMED_WAITING 5、 BLOCKED 6、WAITING 二、线程安全问题 1、线程不安全的原因 2、一个线程不安全的实例 3、加锁操作 4、产生线程不安全的原因 什么是内存可见性呢&#xff1f; 解决方案&#xff1f; 5、指令重排序…

【Linux学习】1-2 新建虚拟机ubuntu环境

1.双击打开VMware软件&#xff0c;点击“创建新的虚拟机”&#xff0c;在弹出的中选择“自定义&#xff08;高级&#xff09;” 2.点击下一步&#xff0c;自动识别ubuntu光盘映像文件&#xff0c;也可以点击“浏览”手动选择&#xff0c;点击下一步 3.设置名称及密码后&#xf…

web - RequestResponse

##Request&Response 1&#xff0c;Request和Response的概述 Request是请求对象&#xff0c;Response是响应对象。这两个对象在我们使用Servlet的时候有看到&#xff1a; 此时&#xff0c;我们就需要思考一个问题request和response这两个参数的作用是什么? request:获取请…

基于微信小程序的竞赛答题小程序开发笔记(一)

开发背景调研 中小学学科答题小程序&#xff0c;适合各中小学校方&#xff0c;老师或者家长。通过互动和参与式学习&#xff0c;小程序能够通过游戏化元素提升学习的积极性和参与度&#xff0c;从而提升学习效率&#xff0c;促进学生自主学习 功能规划 分类题库&#xff1a;…

专题八_链表_算法专题详细总结

目录 链表 1.常用技巧 1&#xff09;画图&#xff01;&#xff01;&#xff01; -> 直观 形象 便于我们理解 2&#xff09;引入虚拟“头”节点 1.便于处理边界条件 2.方便我们对链表进行操作 3.不要吝啬空间&#xff0c;大胆定义变量 4.快慢双指针 1.判断链表是否…

redis学习(014 实战:黑马点评:优惠券秒杀——1人只可以下1单问题解决方案)

黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第54p-第p55的内容 文章目录 一人一单问题分析第一种写法 查询后进行添加第二种写法 加悲观锁在用户上加悲观锁&#xff08;提…

Vue 响应式监听 Watch 最佳实践

一. 前言 上一篇文章我们学习了 watch 的基础知识&#xff0c;了解了它的基本使用方法及注意事项&#xff0c;本篇文章我们继续了解在Vue 中 响应式监听 watch 的妙用。了解 watch 的基础使用请参考上一篇文章&#xff1a; 详解 Vue 中 Watch 的使用方法及注意事项https://bl…

53 语言模型(和之后用来训练语言模型的数据集)_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录理论部分使用计数来建模N元语法总结 代码读取长序列数据随机采样顺序分区 小结练习 理论部分 在上一部分中&#xff0c;我们了解了如何将文本数据映射为词元&#xff0c;以及将这些词元可以视为一系列离散的观测&#xff0c;例如单词或字符…

(务必收藏)推荐市面上8款AI自动写文献综述的网站

在当前的学术研究和论文写作中&#xff0c;AI技术的应用已经变得越来越普遍。特别是在文献综述这一环节&#xff0c;AI工具能够显著提高效率并减少人工劳动。以下是市面上8款推荐的AI自动写文献综述的网站&#xff1a; 一、千笔-AIPassPaper 是一款备受好评的AI论文写作平台&…

java 框架组件

Java 框架是一系列预先编写好的、可复用的软件组件&#xff0c;它们旨在帮助开发者快速构建高质量的应用程序。Java 社区拥有众多优秀的框架&#xff0c;涵盖了从 Web 开发到大数据处理的各个领域。下面是一些流行的 Java 框架及其主要用途&#xff1a; Spring框架&#xff1a;…

基于丹摩智算部署SD3+ComfyUI文生图详解

目录 丹摩智算简介SD3ComfyUI文生图简介 SD3ComfyUI文生图部署步骤1.1、实例创建 操作步骤从HF-mirror下载SD3模型安装git安装ComfyUI 丹摩智算简介 丹摩智算官网&#xff1a;https://www.damodel.com/home 丹摩智算&#xff08;DAMODEL&#xff09;是一款专为AI应用打造的智…

网红挣钱太容易了

你看最近这个三只羊小Y哥&#xff0c;因为月饼质量问题、因为大闸蟹的问题&#xff0c;上了好多次热搜&#xff0c;掉粉了几百万。还是有很多人在赶着要买他们家的东西。 你是他的粉丝&#xff0c;他是你的屠夫。只要冠以“全网最低价”的名号&#xff0c;就会有无数的粉丝跑过…

应用层协议 --- HTTP

序言 在上一篇文章中&#xff0c;我们在应用层实现了一个非常简单的自定义协议&#xff0c;我们在我们报文的首部添加了报文的长度并且使用特定的符号分割。但是想做一个成熟&#xff0c;完善的协议是不简单的&#xff0c;今天我们就一起看看我们每天都会用到的 HTTP协议 。 UR…

华语童声璀璨新星陈千言、陈万语闪耀荣登2024年度最受媒体欢迎女歌手

华语童声璀璨新星陈千言、陈万语闪耀荣登2024年度最受媒体欢迎女歌手 近日&#xff0c;华语乐坛传来一则令人振奋的消息&#xff0c;11 岁的双胞胎姐妹花陈千言和陈万语荣获 2024 华语童声最受媒体欢迎女歌手和第 15 届华语金曲奖优秀童星两项大奖&#xff01; 陈千言和陈万语…