对位运算中问题的阐述


<<          左移操作符(左边抛弃、右边补0)

左移时逻辑移位算术移位相同。

 

>>          右移操作符

逻辑移位:左边用0填充

算术移位:左边用原该值的符号位填充。

C标准说:

无符号数执行所有移位都是逻辑移位。

但对于有符号的数移位,采用哪种移位方式是根据编译器决定的。



使用技巧:(伪代码呈现)

  求二进制最低位 使用(二进制数&1)的高效方法

若 x&(x-1) == 0   则 x为2的次方



对于a<<-4这种有歧义的语句尽量不要使用



# include <stdio.h>    
# include <stdlib.h>    
# include <math.h>    
  
int main()  
{  
    int num = 0;  
    int sum = 0;  
    int temp = 0;  
    int ret = 0;  
  
  
    printf("please input one number\n");  
    scanf_s("%d", &num);  
    for (int b = 0; b < 32; ++b)  
    {  
        temp = ((num >> b) & 1);      /*利用位运算依次获取二进制最低位*/  
        ret = ((ret << 1) | temp);      /*利用位运算较为高效的进行对翻转形式的数值转化*/  
    }  
        //sum += pow((float)2, (31 - b)) * temp;   /*cpp中pow函数有类型的问题,所以对pow(x,y)中的x进行类型(double也行)强转;此外求和还可以利用位运算优化*/  
  
      
  
    printf("\n");  
    printf("%u\n", ret);   /*一定是无符号输出 否则会超出有符号的最大值*/  
    return 0;  
}  
对于这个例子中 有以下论述:

 1  在确定函数原型时 就应该使用无符号类型  否则在输出中添加

printf("%u\n", ret);
避免产生一个比较大的负数


2 核心代码解释
a;   temp = ((num >> b) & 1);     
 &:(左值 右值同为1时 结果为1   二进制位不是1就是0   0&1 = 0;1&1= 1) 1的二进制编码为 0000 0000 0000 0000 0000 0000 0000 0001  任何二进制数位与1,即最低位记录
结合上文提到的求最低位技巧  在for的每次循环中  右移相应的位数 并记录最低位(临时记录)达到从右向左 使用二进制位的目的
 b;    ret = ((ret << 1) | temp);  
|:(左值 右值有一个为1时 结果为1        1|1=1  0|1 =1  0|0=0)   将a中临时记录的最低位   左移(例如 0001 << 1 = 0010 即右边补0)  为或a中临时变量后 达到反转效果
(例子)伪代码如下:
ret = 0
输入NUM = 0111  NUM>>1 = 0011   0011& 0001 = 0001   临时记录 temp
ret(初始为0)<<1 = 0       0  |   0001(temp) = 0001(ret 0001)
NUM>>2=0001   0001 & 0001 = 0001(temp)
ret(0001) << 1 = 0010   0010 | 0001(temp) = 0011 
.......
本例四次操作后 NUM 0111 反转为  1110
.......
for循环 32次结束后   0000 0000 0000 0000 0000 0000 0000 0111    -》   1110 0000 0000 0000 0000 0000 0000 0000


mian over

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值