c语言带进位移位 位运算 移位问题

3436人阅读
&&&&&&&&&& C语言提供了一组位移运算,以便向左或向右移动位。一个是左移位运算x&&k,表示是一个x向左移k位,就丢弃高位的k位,并且右端补k个0。
&&&&&&&&&& 还有一个相应的右移位运算x&&k,但是它的行为就有一点微妙了。一般而言机器支持两种右移位运算:一是算术位移,
&&&&&&&&&& 另外一个是逻辑位运算。逻辑位运算就是左边补k个0,而算术位运算则是左边补k个最高有效位的值。这种做法看上去可能有点奇特,但是我们会发现它对有符号整数数据的运算非常有用。C语言中没有明确的定义用哪种类型位移。对于无符号的必须是逻辑位移。对于有符号的数据两种类型都可以。不幸的是这样不确定行就对程序的移植带来麻烦。一般来说机器都是算术位移,并且许多程序员也是假设机器是这样执行的。
&&&&&&&&&& 另外,java对于如何右位移有明确的定义,那就是表达式x&&k是算术位移,x&&&k是逻辑位移。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:232067次
积分:3105
积分:3105
排名:第3909名
原创:110篇
转载:117篇
评论:26条
(1)(1)(1)(3)(4)(1)(1)(1)(5)(7)(7)(1)(1)(1)(2)(7)(35)(2)(1)(6)(3)(2)(9)(2)(25)(1)(5)(2)(1)(4)(1)(15)(3)(1)(1)(4)(20)(1)(8)(4)(4)(2)(7)(7)(11)(3)问个移位运算与加减法运算的速度问题_c语言吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:256,545贴子:
问个移位运算与加减法运算的速度问题收藏
移位运算速度应该比加减法运算的速度快吧,但是如果是多次(比如3次)移位运算和一次加(减)法运算,哪个比较快?
这个应该和具体的CPU有关。反正在我的机器上移位运算比加法快,但是快不到1倍。
照楼上讲的话, 大于1次的移位和1次的加减乘除之间, 还是选1次的吧..
登录百度帐号我的游戏推荐游戏
后查看最近玩过的游戏
为兴趣而生,贴吧更懂你。或&&问题点数:0&&回复次数:10&&&
移位操作最多几位
移位操作最多几位
来 自:邯郸
等 级:火箭侠
帖 子:1250
专家分:3538
来 自:内蒙古包头
等 级:贵宾
威 望:19
帖 子:3082
专家分:11056
程序代码:#include &stdio.h&
int main(int argc, char* argv[])
&&& int a = <font color=#x;
&&& printf(&%x\n&,a&&<font color=#);
&&& a = <font color=#x;
&&& printf(&%x\n&,a&&<font color=#);
&&& return <font color=#;
}但是别移过了头
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
===========深入&-----------------&浅出============
来 自:邯郸
等 级:火箭侠
帖 子:1250
专家分:3538
其实有时候也可以故意移过头~
所谓的循环移位嘛
等 级:新手上路
帖 子:11
一次移位操作!!
来 自:邯郸
等 级:火箭侠
帖 子:1250
专家分:3538
回复 5楼 半年蚂
等 级:侠之大者
帖 子:140
专家分:470
看到楼主为了这个移位运算的问题如此纠结,只好替楼主去收集点资料了
想必楼主很忙,没有时间去看这些基础的,理论上的东西,
基础是靠自己打的,没有谁可以一夜之间让你有了基础,大牛们是不喜欢跟没有
基础的交流什么编程问题的,我想这一点应该是很多朋友们的共识吧!
好了,少数废话,多干实事!(声明:以下资料大多来源于百度搜索)
移位是一个二元运算符,用来将一个二进制数中的每一位全部都向一个方向移动指定位,溢出的部分将被舍弃,而空缺的部分填入一定的值。在类C语言中,左移使用两个小于符号&&&&表示,右移使用两个大于符号&&&&表示。
位移位运算是将数据看成二进制数,对其进行向左或向右移动若干位的运算。位移位运算符分为左移和右移两种,均为双目运算符。第一运算对象是移位对 象,第二个运算对象是所移的二进制位数。
左移 就是: 丢弃最高位,0补最低位运算符是&&&&&&&&&&&&&& a&&2; //a值不变
右移的概念和左移相反,就是往右边挪动若干位,运算符是&&&&a&&2; //a值不变
右移对符号位的处理和左移不同,对于有符号整数来说,比如int类型,右移会保持符号位不变
int i = 0x;
i = i && 1;&&& //i的值不会变成0x,而会变成0xc0000000
就是说,符号位向右移动 后,正数的话补0,负数补1,也就是汇编语言中的算术右移.同样当移动的位数超过类型的长度时,会取余数,然后移动余数个位.
负数 &&5(假设字长为8位),则得到的是
//============================================================================
以上这些只是一些摘录,希望楼主还是自己找些相关的书籍或资料深入的学习一下,我想你只要不是
问一些基础概念方面的问题,会有很多朋友愿意与你共同探讨的!
&&&&&&&&&&&&&&&&&&&&&&&&&&打扰了!
等 级:新手上路
帖 子:11
唉,其实我是在问:是不是8位计算机被移位的数据是8位、16位计算机被移位的数据是16位、32位计算机被移位的数据是32位啊?
象汇编里的shl ax,1 、是不是也有shl al,1、shl eax,1呢?
手里只有七、八年出产的手机,不让用电脑,连试试都不行啊,悲惨啊!!
等 级:侠之大者
帖 子:140
专家分:470
回楼主,如果你要问的是汇编指令shl的问题,哈哈,这里是c语言!
等 级:新手上路
帖 子:11
C语言不是要转换成汇编语言吗,位数不同,效率不同啊!
你不是知道汇编指令吗,应该知道些吧,可不要藏私啊,
版权所有,并保留所有权利。
Powered by , Processed in 0.025336 second(s), 8 queries.
Copyright&, BCCN.NET, All Rights Reserved36C语言中位运算的巧用
上亿文档资料,等你来发现
36C语言中位运算的巧用
C语言中位运算的巧用;发布于周三by小左;一、位运算实例;1、用一个表达式,判断一个数X是否是2的N次方(;intCountNumberOfOne(intn;intcounter=0;;while(number);counter++;;number&=number-1;;;二、位运算基础;很多高级的动态规
 C语言中位运算的巧用发布于
周三 by 小左 一 、位运算实例1、用一个表达式,判断一个数X是否是2的N次方(2,4,8,16.....),不可用循环语句。
X:2,4,8,16转化成二进制是10,100,。如果减1则变成01,011,。两者做按位与运算,结果如果为0,则X是2的N次方。2、统计一个整数的二进制中1的个数int CountNumberOfOne(int number){int counter = 0;while (number){counter++;number &= number - 1 ;}}二、位运算基础很多高级的动态规划题目或者一些基础的运算往往需要较高的执行效率和较低的空间需求,或者需要表示一些状态集合,而位运算刚好能满足这一切。
很多的时候,恰当的位运算使用也能使程序变得更加简洁和优美。1、位运算法则位运算是各位互不影响的,比如A为1010而B为1100,那么有A&B=1000
~A= (1的个数是取决于A的类型的,这里认为A的类型是8位整型)另外两种位运算是位移运算a&&b和a&&b。前者表示将a的所有位向左移动b位,后者则表示将a的所有位向右移动b位。对于非负整数(往往这也是我们最关心的),新空出的位将会被0取代。
比如A为1001,而B为3,那么A&&B则为1001000,A&&B则为1。
大多数情况下可以简单地认为左移b位就是乘以2^b,而右移b位则是除以(整除)2^b。当然这是存在例外的――对于负数是不能这么简单认为的:比如在GNU GCC/G++ 编译条件下,若A=-1,你会发现对于任何位移运算A&&B,无论B的取值如何,其结果均为-1。因此请注意,在位移运算下务必确保对非负整数进行运算,以免发生不必要的问题。
对于位移运算最常用的操作就是取一个特定的位――比如1&&x就可以来表示一个状态集合――集合中仅元素x存在而没有任何其他元素――因为其他的所有位均为0。2、对于集合的表示大多数时候,我们可以用一个整数来表示一个包含不超过32(当然如果使用64位整型变量也可以是64个)个元素的集合――对于每一个位,如果元素为1,则表示存在当前位所对应的集合成员,如果是0,则表示这个集合成员是不存在的。
比如A=1011 就可以表示集合{0,1,3},而上面提到的1&&x就表示集合{x}。下面我们就能推导出一些直观的集合运算。
我们定义 ALL_BITS 为全集即各二进制位均为1的数。
集合的并 A|B
集合的交 A&B
集合的差 A& ~B
ALL_BITS^A
添加特定元素bit A|=1&&bit
清除特定元素bit A^=1&&bit
取出特定元素bit A&=1&&bit
判断是否存在特定元素bit (A&1&&bit)!=0三、基本技术这里列举一些常用的位运算技术。1、交换技术即不利用第三方进行数的交换,这里给出代码段。swap(a, b){a^=b;b^=a;a^=b;}2、提取技术这里我们要做的就是找出变量a最低位的1和最高位的1分别在什么位置。通过这些手段我们就能轻松地将一个集合分解为若干个元素。(1) 低位技术低位技术即Lowbit技术。相信熟悉树状数组(BIT)的朋友应该并不陌生。
我们对于一个非0数x,现在提取出其最低位的1。这里我提三种不同的写法。
Lowbit(x)=x&(x^(x-1))
Lowbit(x)=x&~(x-1)
Lowbit(x)=x&-x
注意:这里我们求出的是x中最后一个1表示的数,而非其位置。
可以发现,这三种低位函数的写法可谓大同小异――均涉及到了x&和x-1(其实 Cx 可以认为是和 ~(x-1) 等价的,这里利用了负数的存储原理)。
x-1的性质在于:其将一个数最后一个1变成了0,并把原来这个1之后0的位置均变成了1。低位技术正是利用了这个性质。
举一个简单的应用的例子――N&32的全排列问题。Dfs(dep, mask){if(dep == N) output(P);//输出排列K =while (K & 0) {P[dep]= Index(K & -K);[g2]//Index(a)表示a是2的多少次方Dfs(dep+1, mask ^ (K & -K));K ^= K & -K;}}上述程序的复杂度为严格的O(N!),而非O(NN)。
这里只是一个说明,并没有特指全排列问题――这种方式在很多地方可以大大提高程序效率。(2)特殊情况下的简单想法
对于低位技术,一个最简单的想法就是按位扫描依次判断当前位是否为1,这个算法似乎是很慢的――对于一个N位的二进制数,最坏情况需要扫描N次!
但是这只是最坏而非一般――当情况特殊一些――我们要求的不是x的最低位,而是要求出1…2N-1这所有数的低位!
那么在这种情况下,看似缓慢的暴力算法其实是非常不错的――这种算法大约只要均摊2次扫描即可完成检索。
这实际上是最快的方式了。(3)利用分块思想
我们可以打一张1…28-1的表,用于记录每个数的低位(或者是高位),那么对于32位的整数,就可以将其分解为4个8位整数利用预处理得到的表迅速求出低位或者高位了。(4)利用编译器的内置函数
这是C语言的又一大优势。
这里略微提一下两个CPU位处理指令:BSF(前向位扫描)和BSR(反向位扫描)。这两种指令都是内置且非常高效率的。而令人高兴的是――GNU编译器就存在这两种基于这种原理的位处理函数:__builtin_clz(统计最高位0的个数)和__builtin_ctz(统计低位0的个数)。这是对于C和C++编程者最方便和快捷的位处理方式了。
不过要注意的是――这两个函数对于0都没有定义,因此需要特别小心!3、计算二进制表示中1的个数我们很容易判断一个数是不是2的整次幂――比如对于x,那么只要判断x^Lowbit(x)是否为0就可以了。
不过很多时候我们需要统计二进制位中有多少个1(比如当x表示一个集合的时候,我们想知道这个集合中元素的个数),这就要麻烦一点了。
(1)暴力方式
我们可以不断地使用低位技术消去最后一个1。不过这个方法很慢。(2)预处理
我们可以利用递推形式计算出我们所需要的答案,方式非常简单。
用Cnt[x] 来记录x的二进制表示中1的个数,那么:
Cnt[x] = Cnt[x && 1] + (x & 1)
这样就能在线性时间下计算出结果了。(3)利用内置函数
GNU有一个函数 __builtin_popcount 就是实现了我们需要的功能――不过比较遗憾的是,这个函数的实现并不像__builtin_ctz那样利用硬件指令,相反的,它用了一个类似基于预处理方式的按位扫描的实现方式――不过它仍然很高效。(4)有趣的代码
这里再给出一段可以实现上述功能的代码,有兴趣的读者可以自行研究。pop(xx){
//x为32位符号非负整数,或者32位无符号类型x=x-((x&&1)&0x);x=(x&0x)+((x&&2)&0x);x=(x+(x&&4))&0x0f0f0f0f;x=x+(x&&8);x=x+(x&&16);returnx&0x0000003f;} 4、枚举子集当一个数的二进制表示一个集合的时候,位运算的一个巨大优点在于其可以非常轻松和高效地枚举当前集合的所有子集。它的性质在于――如果A是B的真子集,那么可以保证枚举A子集的次数一定小于枚举B的子集的次数。这一点可以大大提高很多压位动态规划题目的实现效率。(1)暴力的方式
最暴力的方式莫过于枚举所有可能的集合,然后一一判断是否为当前集合的子集。如果需要枚举的集合是N个元素的集合,那么对所有可能集合都进行一次枚举操作,花费的时间为O((2N)2)=O(4N)。(2)高效的方式
假设全集有N个元素,那么所有可能的集合就有2N个,对于任意子集S,用N位2进制简单枚举S的所有子集,个数就有2N个,因此如果对所有集合都进行这样一次枚举操作,那么总的时间复杂度就是O((2N)2)=O(4N)。高效的方式。
这里的技巧和低位技术的技巧是类似的――当我们取出最后一个1的时候,这个1将变成0,而比其低位的0将变成1。
与低位技术不同的是,我们并不是要提出某一位1,而是要去除某一位的1,并补上一些我们需要的1。
所以假设当前集合为SuperSet,那么枚举的代码段则为
Iterating_All_SubSet(SuperSet) {i = SuperSwhile (i & 0)i = (i - 1) & SuperS}若当前为N位二进制的集合,并且对所有可行集合进行上述操作,可以证明,操作的总次数为O(3N)。四、有趣的技巧1、计算绝对值abs( x ) {y=x&&31 ;return(x^y)-y;//也可写作 (x+y)^y}这里需要注意的是,上面的x, y 默认为32位有符号整数。2、按位翻转x=((x&0xaaaaaaaa)&&1)|((x&0x)&&1);x=((x&0xcccccccc)&&2)|((x&0x)&&2);x=((x&0xf0f0f0f0)&&4)|((x&0x0f0f0f0f)&&4);x=((x&0xff00ff00)&&8)|((x&0x00ff00ff)&&8);x=((x&0xffff0000)&&16)|((x&0x0000ffff)&&16);如果无符号32位整数x=311=(,那么经过上述操作后x==(。3、枚举恰好含有k个元素的集合我们假设全集为含有N个元素为 {0,1,2,…,N-1},那么代码段可以写成:int s = (1 && k) - 1;while (!(s & 1 && N)){
// 由当前集合 s 计算下一个合法的集合int lo = s & -s;
// 求出低位的1int lz = (s + lo) & ~s;
// 求出比lo高的0中,最低位的0
// 将lz代表的元素加入集合s
s &= ~(lz - 1);
// 将比lz位置低的元素全部清空
s |= (lz / lo / 2) - 1;
// 将集合元素个数补足为k个}当然最后一句话也可以写成s |= (lz && __builtin_ctz(lo && 1)) C 1来避免除法运算。Tags:C/C++, 算法, 优化,0?1614 一 、位运算实例1、用一个表达式,判断一个数X是否是2的N次方(2,4,8,16.....),不可用循环语句。
X:2,4,8,16转化成二进制是10,100,。如果减1则变成01,011,。两者做按位与运算,结果如果为0,则X是2的N次方。2、统计一个整数的二进制中1的个数
int CountNumberOfOne(int number)
int counter = 0;
while (number)
counter++;
number &= number - 1 ;
}二、位运算基础很多高级的动态规划题目或者一些基础的运算往往需要较高的执行效率和较低的空间需求,或者需要表示一些状态集合,而位运算刚好能满足这一切。
很多的时候,恰当的位运算使用也能使程序变得更加简洁和优美。1、位运算法则位运算是各位互不影响的,比如A为1010而B为1100,那么有A&B=1000
~A= (1的个数是取决于A的类型的,这里认为A的类型是8位整型)另外两种位运算是位移运算a&&b和a&&b。前者表示将a的所有位向左移动b位,后者则表示将a的所有位向右移动b位。对于非负整数(往往这也是我们最关心的),新空出的位将会被0取代。
比如A为1001,而B为3,那么A&&B则为1001000,A&&B则为1。
大多数情况下可以简单地认为左移b位就是乘以2^b,而右移b位则是除以(整除)2^b。当然这是存在例外的――对于负数是不能这么简单认为的:比如在GNU GCC/G++ 编译条件下,若A=-1,你会发现对于任何位移运算A&&B,无论B的取值如何,其结果均为-1。因此请注意,在位移运算下务必确保对非负整数进行运算,以免发生不必要的问题。
对于位移运算最常用的操作就是取一个特定的位――比如1&&x就可以来表示一个状态集合――集合中仅元素x存在而没有任何其他元素――因为其他的所有位均为0。2、对于集合的表示大多数时候,我们可以用一个整数来表示一个包含不超过32(当然如果使用64位整型变量也可以是64个)个元素的集合――对于每一个位,如果元素为1,则表示存在当前位所对应的集合成员,如果是0,则表示这个集合成员是不存在的。
比如A=1011 就可以表示集合{0,1,3},而上面提到的1&&x就表示集合{x}。下面我们就能推导出一些直观的集合运算。
我们定义 ALL_BITS 为全集即各二进制位均为1的数。
集合的并 A|B
集合的交 A&B
集合的差 A& ~B
ALL_BITS^A
添加特定元素bit A|=1&&bit 清除特定元素bit A^=1&&bit
取出特定元素bit A&=1&&bit
判断是否存在特定元素bit (A&1&&bit)!=0三、基本技术这里列举一些常用的位运算技术。1、交换技术即不利用第三方进行数的交换,这里给出代码段。swap(a, b){a^=b;b^=a;a^=b;}2、提取技术这里我们要做的就是找出变量a最低位的1和最高位的1分别在什么位置。通过这些手段我们就能轻松地将一个集合分解为若干个元素。(1)低位技术
低位技术即Lowbit技术。相信熟悉树状数组(BIT)的朋友应该并不陌生。
我们对于一个非0数x,现在提取出其最低位的1。这里我提三种不同的写法。 Lowbit(x)=x&(x^(x-1))
Lowbit(x)=x&~(x-1)
Lowbit(x)=x&-x
注意:这里我们求出的是x中最后一个1表示的数,而非其位置。
可以发现,这三种低位函数的写法可谓大同小异――均涉及到了x&和x-1(其实 Cx 可以认为是和 ~(x-1) 等价的,这里利用了负数的存储原理)。
x-1的性质在于:其将一个数最后一个1变成了0,并把原来这个1之后0的位置均变成了1。低位技术正是利用了这个性质。
举一个简单的应用的例子――N&32的全排列问题。Dfs(dep, mask){
if(dep == N) output(P);//输出排列
K = while (K & 0) {
P[dep]= Index(K & -K);[g2]//Index(a)表示a是2的多少次方 Dfs(dep+1, mask ^ (K & -K));
K ^= K & -K;
上述程序的复杂度为严格的O(N!),而非O(NN)。
这里只是一个说明,并没有特指全排列问题――这种方式在很多地方可以大大提高程序效率。包含各类专业文献、外语学习资料、行业资料、专业论文、中学教育、生活休闲娱乐、应用写作文书、36C语言中位运算的巧用等内容。 
  【】 
您可在本站搜索以下内容:
  C语言中的位运算_IT/计算机_专业资料。详细介绍C语言位运算及其应用C 语言中的位运算在计算机程序中,数据的位是可以操作的最小数据单位,理论上可以用“位 运算...
  C语言中的位运算C语言中的位运算隐藏&& C 语言中的位运算 0 推荐 在计算机程序中,数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的...
 c 语言源代码: #include &stdio.h& main() { int a=84; int b = printf(&%d&,a&b); } 2、“按位或”运算符(|) 两个相应的二进制位中...
  在C 语言中的位运算位运算符的含义 运算符 ~ && && & ^ | 含义 按位求反 左移 右移 按位与 按位异或 按位或 优先级 1 2 2 3 4 s 1:运算符...
 关于C语言位运算的两个例题讲解 cc隐藏&& 举例: 0xs6cf 16 位的一个整数, 从( 对应的二进制即为 1111) 取出从第 4 位开始的 4 个位,即第 4、...
 第8章 位 运 算 C 语言是为描述系统而设计的,与其它高级语言相比,它的一个重要特点是具有汇编语 言的功能,这主要表现在 C 语言提供了特有的位运算功能。 8...
 C 语言位运算练习题一、选择题: (1)以下程序的功能是进行位运算 main() { unsigned char a, a=7^3; b= ~4 & 3; printf(&%d %d &,a,b); ...
  c语言位运算_电脑基础知识_IT/计算机_专业资料。位运算一、基本概念: 1、概念:C 语言提供了对二进制数中的某个位或某几位进行操作的 运算符,称为位运算。 ...
赞助商链接
别人正在看什么?
赞助商链接

我要回帖

更多关于 c语言带进位移位 的文章

 

随机推荐