`

学会用位操作解决问题

 
阅读更多

学会用位操作解决问题,下面给出常用解决方法:

 

检测一个无符号数是不为2^n-1(^为幂):   x&(x+1)   

 

  将最右侧0位改为1位:   x   |   (x+1)   

 

  二进制补码运算公式:   

  -x   =   ~x   +   1   =   ~(x-1)   

  ~x   =   -x-1     

  -(~x)   =   x+1   

  ~(-x)   =   x-1   

  x+y   =   x   -   ~y   -   1   =   (x|y)+(x&y)     

  x-y   =   x   +   ~y   +   1   =   (x|~y)-(~x&y)     

  x^y   =   (x|y)-(x&y)   

  x|y   =   (x&~y)+y   

  x&y   =   (~x|y)-~x   

 

  x==y:         ~(x-y|y-x)   

  x!=y:         x-y|y-x   

  x<   y:         (x-y)^((x^y)&((x-y)^x))   

  x<=y:         (x|~y)&((x^y)|~(y-x))   

  x<   y:         (~x&y)|((~x|y)&(x-y))//无符号x,y比较   

  x<=y:         (~x|y)&((x^y)|~(y-x))//无符号x,y比较   

 

 

  使用位运算的无分支代码:   

 

  计算绝对值   

  int   abs(   int   x   )     

  {   

  int   y   ;   

  y   =   x   >>   31   ;   

  return   (x^y)-y   ;//or:   (x+y)^y   

  }   

 

  符号函数:sign(x)   =   -1,   x<0;   0,   x   ==   0   ;   1,   x   >   0   

  int   sign(int   x)   

  {   

  return   (x>>31)   |   (unsigned(-x))>>31   ;//x=-2^31时失败(^为幂)   

  }   

 

  三值比较:cmp(x,y)   =   -1,   x<y;   0,   x==y;   1,   x   >   y   

  int   cmp(   int   x,   int   y   )   

  {   

  return   (x>y)-(x-y)   ;   

  }   

 

  doz=x-y,   x>=y;   0,   x<y   

  int   doz(int   x,   int   y   )   

  {   

  int   d   ;   

  d   =   x-y   ;   

  return   d   &   ((~(d^((x^y)&(d^x))))>>31)   ;   

  }   

 

  int   max(int   x,   int   y   )     

  {   

  int   m   ;   

  m   =   (x-y)>>31   ;     

  return   y   &   m   |   x   &   ~m   ;   

  }   

 

  不使用第三方交换x,y:   

  1.x   ^=   y   ;   y   ^=   x   ;   x   ^=   y   ;   

  2.x   =   x+y   ;   y   =   x-y   ;   x   =   x-y   ;   

  3.x   =   x-y   ;   y   =   y+x   ;   x   =   y-x   ;   

  4.x   =   y-x   ;   x   =   y-x   ;   x   =   x+y   ;     

 

  双值交换:x   =   a,   x==b;   b,   x==a//常规编码为x   =   x==a   ?   b   :a   ;   

  1.x   =   a+b-x   ;   

  2.x   =   a^b^x   ;   

 

  下舍入到2的k次方的倍数:   

  1.x   &   ((-1)<<k)   

  2.(((unsigned)x)>>k)<<k   

  上舍入:   

  1.   t   =   (1<<k)-1   ;   x   =   (x+t)&~t   ;   

  2.t   =   (-1)<<k   ;   x   =   (x-t-1)&t   ;   

 

  位计数,统计1位的数量:   

  1.   

  int   pop(unsigned   x)   

  {   

  x   =   x-((x>>1)&0x55555555)   ;   

  x   =   (x&0x33333333)   +   ((x>>2)   &   0x33333333   )   ;   

  x   =   (x+(x>>4))   &   0x0f0f0f0f   ;   

  x   =   x   +   (x>>8)   ;   

  x   =   x   +   (x>>16)   ;   

  return   x   &   0x0000003f   ;   

  }   

  2.   

  int   pop(unsigned   x)   {   

  static   char   table[256]   =   {   0,1,1,2,   1,2,2,3,   ....,   6,7,7,8   }   ;   

  return   table[x&0xff]+table[(x>>8)&0xff]+table[(x>>16)&0xff]+table[(x>>24)]   ;   

  }   

 

  奇偶性计算:   

  x   =   x   ^   (   x>>1   )   ;   

  x   =   x   ^   (   x>>2   )   ;   

  x   =   x   ^   (   x>>4   )   ;   

  x   =   x   ^   (   x>>8   )   ;   

  x   =   x   ^   (   x>>16   )   ;   

  结果中位于x最低位,对无符号x,结果的第i位是原数第i位到最左侧位的奇偶性   

 

 

  位反转:   

  unsigned   rev(unsigned   x)   

  {   

  x   =   (x   &   0x55555555)   <<   1   |   (x>>1)   &   0x55555555   ;   

  x   =   (x   &   0x33333333)   <<   2   |   (x>>2)   &   0x33333333   ;   

  x   =   (x   &   0x0f0f0f0f)   <<   4   |   (x>>4)   &   0x0f0f0f0f   ;   

  x   =   (x<<24)   |   ((x&0xff00)<<8)   |   ((x>>8)   &   0xff00)   |   (x>>24)   ;   

  return   x   ;   

  }   

 

  递增位反转后的数:   

  unsigned   inc_r(unsigned   x)   

  {   

  unsigned   m   =   0x80000000   ;   

  x   ^=   m   ;   

  if(   (int)x   >=   0   )     

  do   {   m   >>=   1   ;   x   ^=   m   ;   }   while(   x   <   m   )   ;   

  return   x   ;   

  }   

 

  混选位:   

  abcd   efgh   ijkl   mnop   ABCD   EFGH   IJKL   MNOP->aAbB   cCdD   eEfF   gGhH   iIjJ   kKlL   mMnN   oOpP   

  unsigned   ps(unsigned   x)   

  {   

  unsigned   t   ;   

  t   =   (x   ^   (x>>8))   &   0x0000ff00;   x   =   x   ^   t   ^   (t<<8)   ;   

  t   =   (x   ^   (x>>4))   &   0x00f000f0;   x   =   x   ^   t   ^   (t<<4)   ;   

  t   =   (x   ^   (x>>2))   &   0x0c0c0c0c;   x   =   x   ^   t   ^   (t<<2)   ;   

  t   =   (x   ^   (x>>1))   &   0x22222222;   x   =   x   ^   t   ^   (t<<1)   ;   

  return   x   ;   

  }   

 

  位压缩:   

  选择并右移字x中对应于掩码m的1位的位,如:compress(abcdefgh,01010101)=0000bdfh   

  compress_left(x,m)操作与此类似,但结果位在左边:   bdfh0000.   

  unsigned   compress(unsigned   x,   unsigned   m)   

  {   

  unsigned   mk,   mp,   mv,   t   ;   

  int   i   ;   

 

  x   &=   m   ;   

  mk   =   ~m   <<   1   ;   

  for(   i   =   0   ;   i   <   5   ;   ++i   )   {   

  mp   =   mk   ^   (   mk   <<   1)   ;   

  mp   ^=   (   mp   <<   2   )   ;   

  mp   ^=   (   mp   <<   4   )   ;   

  mp   ^=   (   mp   <<   8   )   ;   

  mp   ^=   (   mp   <<   16   )   ;   

  mv   =   mp   &   m   ;   

  m   =   m   ^   mv   |   (mv   >>   (1<<i)   )   ;   

  t   =   x   &   mv   ;   

  x     =   x   ^   t   |   (   t   >>   (   1<<i)   )   ;   

  mk   =   mk   &   ~mp   ;   

  }   

  return   x   ;   

  }   

 

 

  位置换:   

  用32个5位数表示从最低位开始的位的目标位置,结果是一个32*5的位矩阵,   

  将该矩阵沿次对角线转置后用5个32位字p[5]存放。   

  SAG(x,m)   =   compress_left(x,m)   |   compress(x,~m)   ;   

  准备工作:   

  void   init(   unsigned   *p   )   {   

  p[1]   =   SAG(   p[1],   p[0]   )   ;   

  p[2]   =   SAG(   SAG(   p[2],   p[0]),   p[1]   )   ;   

  p[3]   =   SAG(   SAG(   SAG(   p[3],   p[0]   ),   p[1]),   p[2]   )   ;   

  p[4]   =   SAG(   SAG(   SAG(   SAG(   p[4],   p[0]   ),   p[1])   ,p[2]),   p[3]   )   ;   

  }   

  实际置换:   

  int   rep(   unsigned   x   )   {   

  x   =   SAG(x,p[0]);   

  x   =   SAG(x,p[1]);   

  x   =   SAG(x,p[2]);   

  x   =   SAG(x,p[3]);   

  x   =   SAG(x,p[4]);   

  return   x   ;   

  }   

 

  二进制码到GRAY码的转换:   

  unsigned   B2G(unsigned   B   )   

  {   

  return   B   ^   (B>>1)   ;   

  }   

  GRAY码到二进制码:   

  unsigned   G2B(unsigned   G)   

  {   

  unsigned   B   ;   

  B   =   G   ^   (G>>1)   ;   

  B   =   G   ^   (G>>2)   ;   

  B   =   G   ^   (G>>4)   ;   

  B   =   G   ^   (G>>8)   ;   

  B   =   G   ^   (G>>16)   ;   

  return   B   ;   

  }   

 

  找出最左0字节的位置:   

  int   zbytel(   unsigned   x   )   

  {   

  static   cahr   table[16]   =   {   4,3,2,2,   1,1,1,1,   0,0,0,0,   0,0,0,0   }   ;   

  unsigned   y   ;   

  y   =   (x&0x7f7f7f7f)   +   0x7f7f7f7f   ;   

  y   =   ~(y|x|0x7f7f7f7f)   ;   

  return   table[y*0x00204081   >>   28]   ;//乘法可用移位和加完成   

  }   

分享到:
评论

相关推荐

    怎样查看计算机是32位还是64位操作系统.pdf

    如果我们的计算机是64位操作系统,那么我们就需要选择64位的硬件设备,以便提高计算机的使用效率。 查看操作系统位数的方法非常重要,我们应该了解操作系统位数的重要性,并且学会查看操作系统位数的方法。这可以...

    编制计算机解决问题.doc

    特别是针对利用计算机程序语言解决实际问题,课程标准定位在掌握、体会和了解三个层次,旨在让学生不仅学会使用现成的工具软件,还能通过编写程序解决实际问题,了解计算机程序解决问题的基本步骤和方法。...

    四年级数学上册5解决问题的策略5.1.1用列表的方法解决求两积之和差的实际问题教学反思素材苏教版

    4. **实践操作**:为了使学生更好地掌握列表法的应用技巧,可以设计一些实践活动,如小组讨论、案例分析等,让学生在实际操作中发现问题、解决问题。 5. **反馈与调整**:教师应及时收集学生在使用列表法过程中...

    小学数学三年级下册用估算解决问题PPT教案.pptx

    本课件是针对小学数学三年级下册学生设计的,主要讲解如何使用估算来解决实际问题。以下是对核心知识点的详细说明: 1. **口算与估算基础**: - 口算练习包括640÷8、500÷5、4200÷6和1200÷2,这些都是基础的除...

    三年级数学下册第4单元两位数乘两位数4.9用除法两步计算解决问题课时练新人教版

    这个单元的4.9部分特别强调了如何通过除法进行两步计算来解决问题,这对于培养学生的逻辑思维和计算能力至关重要。在这个过程中,学生不仅需要掌握基本的乘除法运算,还需要学会分析问题,合理安排计算步骤。 首先...

    C程序设计五百例--用c语言解决数学建模问题

    这个程序展示了如何用C语言实现数组和循环结构来处理组合问题,同时体现了逻辑判断在解决问题中的应用。 【程序2】涉及的是基于条件的奖金计算问题。程序首先定义了不同利润区间对应的奖金比例,然后根据输入的利润...

    三年级数学上册6多位数乘一位数6.2.5解决问题教学反思新人教版

    在“三年级数学上册6多位数乘一位数6.2.5解决问题教学反思新人教版”这一主题中,我们可以深入探讨几个关键的数学知识点和教育方法。首先,估算能力是小学生数学学习中不可或缺的一项技能。它不仅在日常生活中有广泛...

    五年级数学上册 解决问题的策略教学反思 苏教版 教案.doc

    这个单元的引入旨在培养学生的逻辑思维能力和解决问题的方法论,让学生学会运用有效的策略来解决实际的数学问题。教学反思是教师对教学过程的深度思考,对于提升教学质量具有重要意义。 首先,我们要理解策略在数学...

    苏教版数学四年级上册解决问题的策略PPT学习教案.pptx

    通过这种方式,学生不仅学会了如何整理信息,还锻炼了提出问题和解决问题的能力。 总结来说,本节内容强调了列列表法在解决实际问题中的应用,它是一种有效的策略,能帮助学生组织信息,简化复杂问题,并提高解题...

    电子学会 编程等级考试 C语言 1级-10级 学习资料集(2023.05.26)B.pdf

    4. **递归**:理解和运用递归函数解决问题。 5. **排序与搜索算法**:学习并实现各种排序(如冒泡、选择、插入、快速等)和搜索(如线性、二分)算法。 6. **错误处理**:理解并使用`errno`和`perror`处理运行时错误...

    电子学会青少年软件编程能力等级考试Python二级所有知识点.pdf

    Python编程能力等级考试二级主要针对青少年,旨在提升他们的编程技能,特别是Python语言的掌握程度...通过这样的考试,学生不仅能够学习到Python的基本语法,还能培养解决问题的能力,为未来的编程学习打下坚实的基础。

    郭天祥十天学会单片机种子文件

    郭天祥会教你如何使用调试器进行断点设置、变量查看、步进执行等,帮助你快速定位和解决问题。 通过郭天祥的《十天学会单片机》教程,读者不仅可以掌握单片机的基础知识,还能培养实际操作和问题解决能力,为今后的...

    总复习二以内的退位减法和解决问题新人教一年级下册学习教案.pptx

    6. **解决问题**:这部分引入了实际情境,如小红和小丽折花的问题,红旗小学植树的问题等,这些题目要求学生运用所学的减法知识来解决实际问题,提高他们的应用能力。例如,小红折了几朵花的问题可以通过总数减去...

    57复习统计与可能性、解决问题的策略.doc

    在本节复习课中,主要涉及了统计与可能性、解决问题的策略这两个核心概念,同时强化了计算器的使用、多位数的认识以及求近似数的方法。以下是各知识点的详细说明: 1. **计算器的使用**: - 学生需要了解计算器的...

    十天学会单片机_100个实例

    每个实例都为学习者提供了一个动手实践的机会,通过这些实践,学习者不仅能掌握单片机的基本知识,还能提升解决问题和设计控制系统的能力。对于希望快速入门并精通单片机技术的人来说,这是一个非常实用的资源。

    program_十天学会msp430单片机实验例程_

    7. **09_UART_Debugging**:通过 UART 进行调试,可能包括使用串口通信工具查看 MSP430 输出的信息,以诊断和解决问题。 8. **13_Timer_Interruption**:定时器中断是 MSP430 中的重要功能,实验可能讲解如何设置...

    郭天祥10天学会单片机 第7课课后习题答案

    通过解答这些习题,学习者可以检验自己对单片机基础知识的掌握程度,同时提升解决问题的能力。在实际操作中,遇到问题时,需要理解错误信息,调整代码或检查硬件连接,这都是单片机学习过程中的宝贵经验。 总的来说...

    新人教版三年级上册数学 第9课时 用乘除混合解决归一问题 重点习题练习复习课件.pptx

    通过这些习题,学生可以不断提升他们的逻辑思维和解决问题的能力,同时也能更好地理解和掌握乘除混合运算的规则。 总的来说,三年级上册的数学学习旨在培养学生的计算能力和问题解决技巧,而“用乘除混合解决归一...

    十天学会MSP430程序

    【MSP430简介】 MSP430是由德州仪器(Texas Instruments)开发的一系列超低功耗、高性能的16位微控制器,广泛应用于各种嵌入式系统...通过这样的学习方式,不仅能够快速掌握MSP430F149,还能培养解决实际问题的能力。

    新人教二年级上数学排列问题PPT课件.pptx

    学生可以使用实物操作、书写或绘画的方式,例如用1、2和3这三个数字去组合不同的两位数,同时强调在尝试过程中要保持思维的有序性,避免遗漏和重复。在这个阶段,学生们可能会发现,尽管只有三个数字,但通过有序...

Global site tag (gtag.js) - Google Analytics