编程中 常见的位运算问题
来源:互联网 发布:考试软件哪个好 编辑:程序博客网 时间:2024/05/18 00:13
常见的位运算问题
二进制数和字符串一样都是编程问题中常遇见的一系列问题 ,许多人觉得很难 ,为什么呢?
因为 ,里面计算可能会用的一些想不到的公式 和 计算思路 。
所以 ,许多的人觉得二进制问题很难实现 。
另外 ,在编程中的许多问题如果使用位运算的方法解决的话,可能会更简单。当然也可能没什么效果哦。
编程中的位运算要用到位操作符
位操作符包括
& 与
| 或
^ 异或
接下就由我向大家介绍一些这样的题目(可以使用位运算计算的):
1、两数交换(不允许创建临时变量)
两个数的交换问题,相信的大家都不是很陌生吧 !!
这是一个很简单的问题 ,但是就是有一些变态就是爱给人出难题 ————说不能创建临时变量
看到后是不是很无奈啊;
下面我来讲几种方法吧!!
方法一:
a = a+b;//////a现在等于a 与 b的和
b = a -b;//////b现在等于 (a 与 b的和) -b 为 a最初的值
a = a -b;//////a现在等于 (a 与 b的和) -b 为 b最初的值(因为b的当前值为a的最初值)
void Swap(int *a,int *b){ *a = *a+*b; *b = *a -*b; *a = *a -*b; }但是这个方法有个缺陷 ,就是两数相加 ,有可能会超出整型值的范围。
方法二:
既然加减法可行 ,当然也可以了
a = a*b;//////a现在等于a 与 b的积
b = a /b;//////b现在等于 (a 与 b的积) /b 为 a最初的值
a = a /b;//////a现在等于 (a 与 b的积) /b 为 b最初的值(因为b的当前值为a的最初值)
<span style="font-size:18px;">void Swap(int *a,int *b){ *a = *a**b; *b = *a /(*b); *a = *a /(*b); }</span>但是,这个方法也是有缺陷的,就是 除数不能为零
方法三:
就是使用异或的方法
a = a^b;//////a现在等于a 与 b异或的结果
b = a^b;//////b现在等于 (a 与 b异或的结果) ^b 为 a最初的值
a = a^b;//////a现在等于 (a 与 b异或的结果) ^b 为 b最初的值(因为b的当前值为a的最初值)
<span style="font-size:18px;">void Swap(int *a,int *b){ *a = *a^*b; *b = *a ^*b; *a = *a ^*b; }</span>
这就是将平常的问题使用二进制的方法解决。。
2、计算一个整数二进制形式中1的个数
写一个函数返回参数二进制中 1 的个数
比如: 15 0000 1111 4 个 1
比如: 15 0000 1111 4 个 1
这个问题如果用平常的方法一个一个的算的话,写出来的代码会很繁琐 ,同样错误也不少
下面就让哥来介绍一种简单方法吧
要想解决这个问题就要 知道一个公式
n = n&(n -1);
这个公式只要运行一次 n的二进制式中就少一个 1
例如 :
n = 15
1111
n = 15&14
1111 & 1110 = 14
n = 14&13
1110 & 1101 = 12
n = 12&11
1100 & 1011 = 8
n = 8 & 7
1000&0111 = 0
运行了四次 所以 15的二进制数中有4个1
int count_one_bits(int value){ int ret = 0; while(value) {value = value &(value-1);ret++; } return ret;}
3、计算一个整数二进制形式中0的个数
既然有求二进制数中1的个数 ,就肯定有求 0的个数的
写一个函数返回参数二进制中 0的个数
比如: 15 0000 0000 0000 0000 0000 0000 0000 1111 28 个 1
比如: 15 0000 0000 0000 0000 0000 0000 0000 1111 28 个 1
当然,你可以先求出1的个数 ,然后一减就是 0的个数
下面就让哥再来介绍一种简单方法吧
n = n|(n + 1);
例子就不用举了 ;和求一的个数差不多
int count_zero_bits(int value){ int ret = 0; while(value+1) {value = value |(value+1);ret++; } return ret;}
4、将二进制位模式从左到右翻转后的值
编写函数:
unsigned int reverse_bit(unsigned int value);
这个函数的返回 值value的二进制位模式从左到右翻转后的值。
例如
在32位机器上25这个值包含下列各位:
00000000000000000000000000011001
翻转后:(2550136832)
10011000000000000000000000000000
程序结果返回:
2550136832
unsigned int reverse_bit(unsigned int value);
这个函数的返回 值value的二进制位模式从左到右翻转后的值。
例如
在32位机器上25这个值包含下列各位:
00000000000000000000000000011001
翻转后:(2550136832)
10011000000000000000000000000000
程序结果返回:
2550136832
代码实现:
unsigned int reverse_bit(unsigned int value){unsigned int ret = 0 ;int i = 0;int num = 0;for(i = 0;i<32;i++){num = (value>>i)&1;//求出每一位二进制位的数ret += num* pow(2,31-i);//根据要求重新计算}return ret;}
5、找出数组中只出现一次的两个数
原题目是这样的:
一组数据中只有两个数字出现了一次。
其他所有数字都是成对出现的。请找出这个数字。(使用位运算)
其他所有数字都是成对出现的。请找出这个数字。(使用位运算)
题目中明确表示要使用位运算来解决这个问题;
在这里就要知道位操作符(^ 异或)的特点是什么?
异或操作符 :
1、两个相同的数异或后为 0 ;
2、任何一个数与0异或的结果都是这个数。
在这个题目中就要运用到这个特点 ,
要解决这个问题 :就要将数组中的数全部异或 得到的结果 就是只出现一次的两个数异或后的结果 ,
然后,根据这个结果将数组分为两部分,将这两部分的数各自异或后得到的结果就是要找的这两个数...
代码实现
void search_date(int arr[],int len ,int *num1,int *num2)//num1 与 num2为要找的那两个数的地址{int num = 0;int i = 0 ;int m = 0 ;for(i = 0;i<len;i++){num ^=arr[i];}//求出所有数异或的结果num while(((num>>m)&1)!=1)//找到num二进制式中为1的位{m++;}for(i = 0 ;i<len;i++){if(((arr[i]>>m)&1) ==1)//将数组分为两组*num1 ^=arr[i];//各自异或else*num2 ^=arr[i];}}
1 0
- 编程中 常见的位运算问题
- 常见的位运算
- 常见的位运算技巧
- 笔试面试中常见的位运算用法
- 笔试中常见的位运算案例分析
- linux下C语言编程之位运算和字符串运算中遇到的问题:20120707苏嵌实训第第六天
- 位运算的问题
- 有关面试中常见位运算总结
- java中位运算问题
- 位运算的常见操作和题目
- 常见的位运算用法总结
- java中常见的编程问题
- Android中巧妙的位运算(Android源码中常见的一些flag的运算的理解)
- Android中巧妙的位运算(Android源码中常见的一些flag的运算的理解)
- C 语言中有关常见的运算符问题
- 一个位运算的问题
- 位运算的小问题
- Java位运算的问题
- codeforces--707C. Pythagorean Triples
- Differential signaling best practices
- 设计模式之抽象工厂模式
- 无人驾驶的技术安全风险可以避免吗?
- 覆盖索引
- 编程中 常见的位运算问题
- MySQL单实例安装
- (二)mysql 优化相关
- 转换英文日期
- leetcode_c++:树: Populating Next Right Pointers in Each Node(116)
- Android三种方式实现视频
- TensorFlow源代码学习--1 Session API reference
- Qt 开启自启动程序 启动后仍可读取本地文件
- 提高你开发效率的十五个Visual Studio 2010使用技巧