位运算处理2的n次方的除法

假设X为一个int型变量,请给出一个用来计算x/32的值的函数div32.要求不能使用除法、
乘法、模运算、比较运算、循环语句和条件语句。
可以使用右移、加法以及按位运算。
#include<iostream>
using namespace std;
void div32(int n)
{
    int x=(n>>31)&0x1F;  //偏置常数
    int ans=(n+x)>>5;
    cout<<ans<<endl;
}

int main()
{
    div32(64);
    return 0;                                   
}

这里注意,这个函数是设计用于整除
如果不是整除的话,结果按照C语言的整除规则——只保留整数部分

特别注意!!
要实现C语言的整除规则的话则引入一个偏置常数是必要的!

不然如下:

#include<iostream>
using namespace std;
int main()
{
    int n=-3>>1;
    cout<<n<<endl;
    return 0;                                   
}

执行结果:
-2
请按任意键继续. . .

当被除数是负数且不能整除时,就会出现错误

有人可能会想,加个 if 去判断啊
但是,题目说了不能用条件语句!

所以,还是得引入偏置常数,下面具体来看看偏置常数是如何得来的

如果大家多测几个数据,就会发现,如果直接进行位移操作,误差只是1而已
这个“1”,其实可以看作是该数的机器码向右位移后数值位的最后一位
-3的机器码——1…1101
向右位移1位——1…110—— -2
要修复那个BUG的话,只要设置好什么条件下给数值位最后一位进一位就OK了
那么究竟是什么条件下呢?

其实,这个条件就是是否整除
下面拿除以4简单分析一下
拿八位的机器码来看
0000 0100 ——真值:4
大家可以发现,往1左边走,分别是8, 16, 32 …
这些左边的数字完全可以除以4,也就是说不会出现除不尽4的情况
主要是1右边的数—— 2,1
举个例子:
0000 0110—— 6 除不尽4
那么,规律就已经出来了~

是否可以被4整除,就看4在机器码中对应的数位右边是否有值
若没有,则可以整除
若有,则不能整除

现在看到刚刚给出的-3的例子
-3 的机器码——1…101
除以2,则看2对应的数位——倒数第二位的右边
有1——不能整除
则要在位移后加一
1…10+1 = 1…11
即为-1 ——加了1才是正确的

回到除以32的题目

int x=(n>>31)&0x1F;  //偏置常数

其实,这一个偏置常数为什么这么设置的答案已经出来了

x=11111=31(n为负数)

x=00000=0(n为正数)

int ans=(n+x)>>5;

可以发现,偏置常数11111则是机器码的末尾5位——对应除数32
n+x——只要n机器码的末尾5位中存在一个1,则这个加法会实现前面提到的——“加一”
——在位移后数值位的最后一位加一

以上!解析完毕~

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值