`
cloudtech
  • 浏览: 4605947 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

位运算符及其应用

 
阅读更多

一、C语言的六种位运算符:

& 按位与

| 按位或

^ 按位异或

~ 取反

<< 左移

>> 右移

1.按位与运算

按位与运算符"&"是双目运算符。

其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。

例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码) 00000001 (1的二进制补码)可见9&5=1。

按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 运算 ( 255 的二进制数为0000000011111111)。

main(){
	int a=9,b=5,c;
	c=a&b;
	printf("a=%d\nb=%d\nc=%d\n",a,b,c);
}

2.按位或运算

按位或运算符“|”是双目运算符。

其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。

例如:9|5可写算式如下: 00001001|00000101

00001101 (十进制为13)可见9|5=13

main(){
	int a=9,b=5,c;
	c=a|b;
	printf("a=%d\nb=%d\nc=%d\n",a,b,c);

3.按位异或运算

按位异或运算符“^”是双目运算符。

其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现。

例如9^5可写成算式如下: 00001001^00000101 00001100 (十进制为12)

main(){
	int a=9;	
	a=a^15;
	printf("a=%d\n",a);
}

4. 求反运算

求反运算符~为单目运算符,具有右结合性。

其功能是对参与运算的数的各二进位按位求反。

例如~9的运算为: ~(0000000000001001)结果为:1111111111110110

5. 左移运算

左移运算符“<<”是双目运算符。左移n位就是乘以2的n次方。

其功能把“<<”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。

1)例: a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。

2)例:

int i = 1;

i = i << 2; //把i里的值左移2位

也就是说,1的2进制是000...0001(这里1前面0的个数和int的位数有关,32位机器,gcc里有31个0),左移2位之后变成 000...0100,也就是10进制的4,所以说左移1位相当于乘以2,那么左移n位就是乘以2的n次方了(有符号数不完全适用,因为左移有可能导致符号变化,下面解释原因)

需要注意的一个问题是:int类型最左端的符号位和移位移出去的情况. 我们知道,int是有符号的整形数,最左端的1位是符号位,即0正1负,那么移位的时候就会出现溢出,

例如:

int i = 0x40000000; //16进制的40000000,为2进制的01000000...0000

i = i << 1;

那么,i在左移1位之后就会变成0x80000000,也就是2进制的100000...0000,符号位被置1,其他位全是0,变成了int类型所能表示的最小值,32位的int这个值是-2147483648,溢出.如果再接着把i左移1位会出现什么情况呢?在C语言中采用了丢弃最高位的处理方法,丢弃了1之后,i的值变成了0.

左移里一个比较特殊的情况是当左移的位数超过该数值类型的最大位数时,编译器会用左移的位数去模类型的最大位数,然后按余数进行移位,如:

int i = 1, j = 0x80000000; //设int为32位

i = i << 33; // 33 % 32 = 1 左移1位,i变成2

j = j << 33; // 33 % 32 = 1 左移1位,j变成0,最高位被丢弃

在用gcc编译这段程序的时候编译器会给出一个warning,说左移位数>=类型长度.那么实际上i,j移动的就是1位,也就是33%32后的余数.在gcc下是这个规则,别的编译器是不是都一样现在还不清楚.

总之左移就是: 丢弃最高位,0补最低位

6. 右移运算

右移运算符“>>”是双目运算符。右移n位就是除以2的n次方

其功能是把“>>”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。

例如:设 a=15,a>>2 表示把000001111右移为00000011(十进制3)。

应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时, 最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。

右移对符号位的处理和左移不同:

对于有符号整数来说,比如int类型,右移会保持符号位不变,例如:

int i = 0x80000000;

i = i >> 1; //i的值不会变成0x40000000,而会变成0xc0000000

就是说,对于有符号数, 符号位向右移动后,正数的话补0,负数补1,

对于有符号数,在右移时,符号位将随同移动:

当为正数时, 最高位补0,

而为负数时,符号位为1,

也就是汇编语言中的算术右移.同样当移动的位数超过类型的长度时,会取余数,然后移动余数个位.

最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。


负数10100110 >>5(假设字长为8位),则得到的是 11111101

总之,在C中,左移是逻辑/算术左移(两者完全相同),右移是算术右移,会保持符号位不变.实际应用中可以根据情况用左/右移做快速的乘/除运算,这样会比循环效率高很多. x>>1; //相当于 x /= 2x<<1; //相当于 x *= 2x>>2; // x /=4x<<2; // x *= 4x>>3; // x /= 8x<<3; // x *= 8以此类推.

无符号:

main(){
	unsigned a,b;
	printf("input a number: ");
	scanf("%d",&a);
	b=a>>5;
	b=b&15;
	printf("a=%d\tb=%d\n",a,b);

}

请再看一例!

main(){
    char a='a',b='b';
    int p,c,d;
    p=a;
    p=(p<<8)|b;
    d=p&0xff;
    c=(p&0xff00)>>8;
    printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d);
}


二、异或操作的妙用

1.使特定位翻转 要使哪几位翻转就将与其进行∧运算的该几位置为1即可。

2 与0相∧,保留原值.

3.交换两个值,不用临时变量.

我们可以在不用引入其他变量就可以实现变量值的交换

用异或操作可以实现:

a = a^b; //(1)
b = a^b; //(2)
a = a^b; //(3)

异或操作满足结合律和交换律,且由异或操作的性质知道,对于任意一个整数a^a=0;

证:(第(2)步中的a) a = a^b =(将第(1)步中的b代入b) a^(a^b) = b;

(第(3)步中的b)b =a^b = (将第(1)步中的b代入b,将第(2)步中的a代入a) a^b^a^a^b = a^a^a^b^b = a;

三 、位与运算

1 . 清零A数中为1的位,B中相应位为0。然后使二者进行&运算,即可达到对A清零目的。

2 . 取一个数中某些指定位 取数A的某些位,把数B的某些位置1,就把数A的某些位与1按位与即可。

3 . 保留一位的方法 数A与数B进行&运算,数B在数A要保留的位1,其余位为零。

4 . 判断奇偶性将变量 a的奇偶性。a与1做位与运算,若结果是1,则 a是奇数;将 a与1做位与运算,若结果是0,则 a是偶数。


4、应用举例

1 .判断int型变量a是奇数还是偶数

a&1 = 0 偶数
a&1 = 1 奇数

2 . 取int型变量a的第k位

(k=0,1,2……sizeof(int)),即a>>k&1

3 . 将int型变量a的第k位清0,即a=a&~(1<<k)

4 . 将int型变量a的第k位置1, 即a=a|(1<<k)


5 . int型变量循环左移k次,即a=a<<k|a>>16-k (设sizeof(int)=16)

6 . int型变量a循环右移k次,即a=a>>k|a<<16-k (设sizeof(int)=16)

7. 整数的平均值

对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会绯龅模颐怯萌缦滤惴ǎ?/DIV>

int average(int x, int y) //返回X,Y 的平均值
{
return (x&y)+((x^y)>>1);
}

8 . 判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂

boolean power2(int x)
{
return ((x&(x-1))==0)&&(x!=0);
}

9 不用temp交换两个整数
void swap(int x , int y)
{
x ^= y;
y ^= x;
x ^= y;
}

php:
$a ='dd';
$b = 'bb';

$a = $a ^ $b;
$b = $a ^ $b;
$a = $a ^ $b;
echo $a,' ', $b;


10 计算绝对值
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y
}


11. 取模运算转化成位运算 (在不产生溢出的情况下)
a % (2^n) 等价于 a & (2^n - 1)


12 乘法运算转化成位运算 (在不产生溢出的情况下)
a * (2^n) 等价于 a<< n

13. 除法运算转化成位运算 (在不产生溢出的情况下)
a / (2^n) 等价于 a>> n
例: 12/8 == 12>>3

14 . a % 2 等价于 a & 1 ( a & log2(2))
a % 4等价于 a & 2 ( a & log2(4))

.....
a % 32 等价于 a & 5


15 if (x == a) x= b;
   else x= a;
等价于 x= a ^ b ^ x;

16 x 的 相反数 表示为 (~x+1)

分享到:
评论

相关推荐

    运算符和表达式的运用

    运算符和表达式的运用,算术运算符的使用,流控制符的使用,关系运算符的使用,位运算符的使用

    基于位运算的两种字符串加密解密算法

    目前现有的C和C++的教材书籍中对于位运算的讲解和阐述较为简略,大多都是出于知识体系完整性的考虑而涉及了一些位运算符及其简单的应用 ].这对一些学习程序设计的人来说远远不够,很多学生仅仅知道有位运算符的存在...

    数据机构实验 树及其应用实验

    实现一个重言式的判别程序。逻辑表达式从键盘输入,长度不超过一行;逻辑运算符包括“|”、“&”、“~”,分别表示或、与、非,运算优先程度递增,括号内的运算优先。 注释比较详细了!

    全国计算机二级C语言等级考试视频教程-1-5章

    计算机二级C语言等级考试,43小时,3.3g,视频教程,由于一次只能上传1g,所以分3个资源上传 目录: 第01章 程序设计 第02章 数据和表达式 第03章 输出和输入函数...第15章 位运算符及其功能 第16章 六组文件函数的应用

    全国计算机二级C语言等级考试视频教程-12-16章

    计算机二级C语言等级考试总16章,43小时,3.3g,视频教程,由于一次只能上传1g,所以分3个资源上传 12-16章 总目录: 第01章 程序设计 第02章 数据和表达式 ...第15章 位运算符及其功能 第16章 六组文件函数的应用

    全国计算机二级C语言等级考试视频教程-6-11章

    计算机二级C语言等级考试总16章,43小时,3.3g,视频教程,由于一次只能上传1g,所以分3个资源上传 6-11章 总目录: 第01章 程序设计 第02章 数据和表达式 ...第15章 位运算符及其功能 第16章 六组文件函数的应用

    北邮数值与符号计算实验 快速傅里叶变换及其应用

    1.1 用C++实现复数类,并为其定义必要的运算符。 struct Complex{ double real_; double image_; Complex (void); Complex (double const& real); Complex (double const& real, double const& imag); Complex ...

    Python中的计算器应用程序及其源代码.rar

    Python中的计算器应用程序及其源代码 Python 中的计算器应用程序是一个使用 Python 开发的简单项目。该项目包含数字、运算符和符号,就像普通计算器一样。因此,用户无法自己输入数字,他们只需在计算中单击所需的...

    数据结构实验 堆栈和队列的应用

    实验五 堆栈和队列的应用 一、实验目的 掌握堆栈和队列的使用。 二、实验内容 1、计算数学表达式的值。 输入数学表达式,输出表达式的计算结果。数学表达式由单个数字和运算符“+”、“-”、“*”、“/”、“(、...

    单片机c语言应用100例

    1.1.2单片机应用系统的结构及其工作过程 1.1.3单片机的应用 1.2单片机基础知识 1.2.1数制与数制间的转换 1.2.2单片机中数的表示方法及常用数制的对应关系 1.2.3逻辑数据的表示 1.2.4单片机中常用的基本术语 1.3...

    基于C#语言 “简易计算器” 应用程序及其代码方案

    基于C#语言 “简易计算器” 应用程序及其代码方案 在这个项目中,我们首先在Visual Studio中创建一个新的Windows Forms应用程序项目。接着,在"Form1.cs"文件中,我们添加了必要的代码来设计计算器界面,包括数字...

    精通sql结构化查询语句

    7.6.1 逻辑运算符与IN运算符的组合应用 7.6.2 逻辑运算符与NOT运算符的组合应用 7.6.3 逻辑运算符与数学运算符的组合应用 7.6.4 逻辑运算符与集合运算符的组合应用 7.6.5 数学运算符与NOT运算符的组合应用 7.6.6 ...

    Delphi.7应用教程

    3.1.1 基本的顺序结构语句及其应用 3.1.2 选择结构语句及其基本应用 3.1.3 循环结构语句及其基本应用 3.2 典型实例 3.2.1 典型实例一 3.2.2 典型实例二 3.2.3 典型实例三 3.2.4 典型实例四 3.2.5 典型实例五 3.3 ...

    论文研究 - Chebyshev多项式及其在二维算子上的应用

    推导并讨论了第二类Un(x)的Chebyshev多项式在二维算子函数中的新应用。 它与算符或矩阵的Hamilton-Cayley身份有关,这允许在N维情况下将幂减小并将函数平滑化为所考虑算符的前N-1次幂的叠加。 该方法在二维情况下...

    C语言实验报告.rar

    计算机程序设计实验—— ...实 验 六:一维、二维数组及其应用 实 验 七:字符串及其库函数 实 验 八:函数的定义与调用 实 验 九:函数与数组 实 验 十:结构体与共用体 实验十一:指针及其应用 一个综合大实验报告

    程序设计基础(C) 视频.txt

    1.3.5赋值运算符、复合的赋值运算符及其表达式17 1.3.6条件运算符18 1.3.7位操作运算符18 1.3.8其他运算符20 1.3.9数据类型转换21 1.3.10类型别名22 1.4面向对象设计思想及其实例23 1.4.1程序设计语言的发展23 1.4.2...

    离散数学及其应用(第6版-本科教学版)

    基础:逻辑和证明1.1 命题逻辑1.1.1 引言1.1.2 命题1.1.3 条件语句1.1.4 复合命题的真值表1.1.5 逻辑运算符的优先级1.1.6 翻译语句1.1.7 系统规范说明1.1.8 布尔检索1.1.9 逻辑难题1.1.10 逻辑运算和位运算练习1.2 ...

    精通JavaScript

    • 3.10.htm “++”运算符后置应用 • 3.11.htm “++”运算符前置应用 • 3.12.htm 逗号表达式的连接应用 • 3.13.htm 逗号表达式的连接应用 • 3.14.htm typeof运算符的...

    java编程基础,应用与实例

    3.7.9 位运算符:位与(&)、位或(|)、位异或(^) 34 3.7.10 三目运算符(?:) 35 3.7.11 赋值运算符 36 3.7.12 对象运算符(instanceof) 37 3.8 巩固练习 37 第4章 程序流程控制语句 39 4.1 if语句 39 ...

    Java Web入门经典第八章源代码-by 南邮-陈杨

    167 8.4 EL运算符及其优先级 168 8.4.1 通过EL访问数据 168 8.4.2 在EL中执行算术运算 170 8.4.3 在EL中判断对象是否为空 170 8.4.4 在EL中执行逻辑关系运算 171 8.4.5 在EL中执行条件运算 172 8.5 EL的隐含...

Global site tag (gtag.js) - Google Analytics