关于负整数的移位问题

本文通过一个编程问题引入,探讨了负整数的二进制表示和移位操作。在不使用判断语句的情况下,尝试通过移位找到两个数中的最大者。然而,由于负数移位的特殊性,导致初始方法出现错误。文章深入解析了负整数的反码和补码表示,并指出右移31位会导致-1的结果。最后,提出了一种更优的解决方案:利用算术运算实现无条件的选择最大值。

题目:有两个变量a,b,不用if 、?:、switch 等判断语句,找出两个数中的最大者。

 

分析:我的思路是用a-b,看一下结果是正还是负,不用判断语句,不能与0比较,可以将两者的差值赋给int型变量c,看一下c的最高位是0还是1,同样不能用switch来判断。可以定义一个数组num[2]={a,b},c进行右移位操作,c>>=31(32位操作系统)。当a>b时,c的值为零,返回num【c】,既是a,同理当a<b时,返回num【c】,既是b,因此代码如下:

 

  int a,b;
  cin>>a>>b;
   int num[2]={a,b};
    int c=a-b;
 c>>=31;
 cout<<num[c]<<endl;

 

然而程序的输出结果并不正确,当a大时,没有问题,当b大时,通过单步调试看到c的值为-1!!

 

然后查了一下带符号整数的移位问题,总结如下:

 

1、负整数的二进制表示:

    对于负整数比如-5,

    化为二进制数:10000000 00000000 00000000 00000101

    其反码表示为:11111111 11111111 11111111 11111010

    其补码表示为:11111111 11111111 11111111 11111011

2、负整数的移位:

   比如c=-5; c>>=1;

  则对c的补码进行向右移位,而且右移一位后,高位仍然补上1,(10010000 右移两位后为11100100)

  所以移位后的c的补码表示为: 11111111 11111111 11111111 11111101

                    c的反码表示为:  11111111 11111111 11111111 11111100

                     c的二进制为   : 10000000 00000000 00000000 00000011

   即-3

   若c右移31位,则c的补码表示为: 11111111 11111111 11111111 11111111

                          c的反码表示为:  11111111 11111111 11111111 11111110

                           c的二进制为   : 10000000 00000000 00000000 00000001

   即-1

 

  其实负数的移位这样做还有个好处,就是保证了移位与乘法的关系,左移一位为乘2,右移一位为除2。-5/2=-3

 

 

当然对于这道题来说有更好的解决方法:c=((a+b)+abs(a-b))/2

  

 

 

int c = a - b;
    c = unsigned(c) >> (sizeof(int) * 8 - 1);

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值