位运算实现进制转换(进制转换和位运算的简单应用)
在了解什么是 位运算 之前,让我们先来了解什么是 位 ? 位 指计算机存储信息的最小单位,在二进制数系统中, 位 是通过0或1来表示。在学习一门编程语言的数据类型时,总会告诉我们 int 的存储需要 4个 字节 ,取值范围为 -2 147 483 648 ~ 2 147 483 647 。其实 取值范围 就是通过 位 计算出来的,由于 1 字节 = 8 位 ,所以 int 中的 1 用二进制表示为 0000 0000 0000 0000 0000 0000 0000 0001 。所以 位运算 就是直接对整数在内存中的二进制位进行操作。
为了方便,下面学习中以 int 的 2个字节 演示
十进制转换为二进制
正整数转换为二进制
正整数转换为二进制通常使用 除二倒取余 的方法。下面演示通过此方法求 10 、13 、42 的二进制。
如图,让整数不断的除二,结果余数写在右侧,当商为 0 时,停止。所以10 的二进制为: 0000 0000 0000 1010 ,13 的二进制为 0000 0000 0000 1101 , 42 的二进制为 0000 0000 0010 1010 。 除了使用 除二倒取余
的方法,也可以把二进制位 对应的 十进制表列出来,在进行进制转换时,只需要把十进制数拆成 表中对应十进制的和就可以。如:
1111111111111111327681638481924096204810245122561286432168421
如:10的二进制:10 = 8 2 为:1010 42的二进制:42 = 32 8 2 为:101010 13 的二进制:13 = 8 4 1 为:1101
负整数转换为二进制
在对负整数求二进制时,需要先将负整数对应的正整数转换成二进制,接着对二进制取反,然后对结果再加一。如求 -10 的二进制:
-10 的二进制 先求 10 的二进制 0000 0000 0000 1010 取反: 1111 1111 1111 0101 加 1: 1111 1111 1111 0110
所以 -10 的二进制为 1111 1111 1111 0110 。 注意: 在二进制中的最高位为 符号位 ,0 表示为正数,1表示为负数,所以 int 的最大整数的二进制为 0111 1111 1111 1111 1111 1111 1111 1111 ,取值范围为:
位运算
位运算可以对整型数值的各个位进行操作。位运算符包括下面这几个:
& : 按位与 运算符
当两个整数值 对应位 上都是 1 时,该位返回 1 ,否则返回 0 (同 1 为 1 )。如:
10 & 13 10 : 0000 0000 0000 1010 13 : 0000 0000 0000 1101 ------------------------------------------ 结果:0000 0000 0000 1000
| : 按位或 运算符
当两个整数值 对应位 上都是 0 时,该位返回 0 ,否则返回 1 (同 0 为 0 )。如:
42 | 13 42 : 0000 0000 0010 1010 13 : 0000 0000 0000 1101 ------------------------------------------ 结果:0000 0000 0010 1111
^ : 按位异或 运算符
当两个整数值 对应位 上的数不相同时,该位返回 1 ,否则返回 0 (不同返回 1 )。如:
42 ^ 13 42 : 0000 0000 0010 1010 13 : 0000 0000 0000 1101 ------------------------------------------ 结果:0000 0000 0010 0111
~ : 按位取反 运算符
把整数值 对应位 上的数取反,1 变 0, 0 变 1。
42 : 0000 0000 0010 1010 ------------------------------------------ ~42: 1111 1111 1101 0101
<< : 左移 运算符
X << y 把整数 X 的二进制位,向左移动 y 位。末尾 补 0 。相当于 X * 。
13 << 2 13 : 0000 0000 0000 1101 ---------------------------------------- <<2: 0000 0000 0011 0100 13 << 2 的结果为:52 -----> 13 * (2^2) = 52
>> : 右移 运算符
X >> y 把整数 X 的二进制位,向右移动 y 位。开始处补符号位。相当于 X / 取整数。
13 >> 2 13 : 0000 0000 0000 1101 ---------------------------------------- >>2: 0000 0000 0000 0011 13 >> 2 的结果为:3 -----> 13 / (2^2) = 3
-10 >> 2 -10 : 1111 1111 1111 0110 ---------------------------------------- >>2 : 1111 1111 1111 1101 -10 >> 2 的结果为:-3 -----> -10 / (2^2) = -3
简单应用
判断奇偶
由于奇数的二进制末尾始终是 1 ,因此我们可以通过 x & 1 判断末尾是否有 1 来决定是否是奇数。
// 通过: a&1 的方式取二进制的最后一位。 #include<stdio.h> int main(){ int a = -3; if(a & 1){ printf("奇数:%d\n",a); }else{ printf("偶数:%d\n",a); } return 0; }
交换
在交换中, ^ 运算符的运算结果可以理解成 记录两个数的不同 。好比,我告诉你在一个箱子里有两个不一样颜色的球(红,蓝)。当用手在里面拿出一个蓝球时,里面剩下的球不用看,颜色肯定是红色的。
#include<stdio.h> int main(){ int a = 3; int b = 2; printf("a = %d, b = %d\n",a,b); a = a^b;//告诉 a 和 b 的不同的地方,赋值给 a。 b = a^b;// b 通过不同记录 a,就可以找到原数a,赋值给 b a = a^b;// 此时b的值是原数a,a 通过不同记录 a,就可以找到原数b,赋值给 a printf("a = %d, b = %d\n",a,b); return 0; }
求两个数的平均数
通过 (x & y) ((x ^ y) >> 1) 的方式求两个数的平均数。我的理解是:先通过 (x & y) 取两个数的公共部分,然后通过 ( x ^ y) 把剩余部分相加求和通过 >> 1 除以2。以十进制数为例:(12 8) / 2 ;12 = 8 4, 8 = 8 0;所以公共部分是8,剩余部分是(4 0)/2 = 2 ,平均数为 8 2 = 10;
#include<stdio.h> int avarge(int x, int y){ return (x & y) ((x ^ y) >> 1); } int main(){ int a = 6; int b = 2; printf("a = %d, b = %d,平均数:%d\n",a,b,avarge(a,b)); return 0; }
判断一个数是否是2 的幂次
在二进制中, 2 的幂次 的整数是只含有一个 1 ,如 : 0100 , : 1000 。所以,当我们去掉最后一位的 1 时,结果就变成 0 了。通过 x & (x - 1) 来去除最后一位的 1 。
#include<stdio.h> int main(){ int a = 7; if (a & (a-1)){ printf("a = %d 不是 2 的幂次\n",a); } else{ printf("a = %d 是 2 的幂次\n",a); } return 0; }
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com