取余操作的原理

虽然以前学过,但是已经忘了,在返秦的火车上看到如此问题,于是思考了一下。


C是高级语言,a-(a整除b)*b就不用说了,“整除”是怎么来的?
但相对于二进制运算,汇编也算一种“高级”语言,那么我问,“div”是怎么来的?

来看一个例子,如果除数的数是2的幂次的话:

  • 除数2,二进制为0000 0010,被除数5,二进制为0000 0101。除数-1,即此时除数变为0000 0001,两者进行与操作,结果为0000 0001,余数为1。
  • 除数4,二进制为0000 0100,被除数13,二进制为0000 1101。除数-1,即此时除数变为0000 0011,两者进行与操作,结果为0000 0001,余数为1。
  • 除数8,二进制为0000 1000,被除数47,二进制为0010 1111。除数-1,即此时除数变为0000 0111,两者进行与操作,结果为0000 0111,余数为7。

原理明白了吧,但这种方法仅仅适用于除数为2的幂次数的时候。
另,这种方法会出现在位图法的位向量操作中,看着是与操作,实际上就是取余。

#define MAX 1000000  
#define SHIFT 5  
#define MASK 0x1F  
#define DIGITS 32  
  
int a[1+MAX/DIGITS];
//置指定位为1
void setbit(int n) 
{ 
 a[n>>SHIFT] |= (1<<(n&MASK)); 
}
//清空指定位                                              
void clearbit(int n)  
{  
 a[n>>SHIFT] &= ~(1<<(n&MASK));  
}
//检测指定位是否已设置为1    
int test(int n)  
{  
    return a[n>>SHIFT] & (1<<(n&MASK)); 
} 

再次言归正传。
取余是通过电路进行二进制除法来实现的,简略的原理图(具体的要复杂很多)我记得在数电的教科书上有,改天我查到了补上。
那么二进制除法是怎样的呢?其实网上一搜一堆原理。(TAT我在高铁上还以为是我自创来着)
(我们可以直接用减法来实现,但这样的话,如果是10324除以3,就会循环非常多次。)
针对这种情况,我的想法是:
1,将除数左移,至与被除数的最高位对齐或者小一位。(小一位是因为待会得用被除数减去左移后的除数,这个时候被除数肯定>(除数*某个2的n次))
2,被除数减去左移后的除数。
3,除数左移,这个时候,被除数肯定>(除数*某个2的n1次)
。。。。
不停迭代,直至被除数<除数,这个时候被除数就是余数。
我们先来看不考虑商,仅仅考虑取余

我们随便找两个数,假设是2381除以7。
2381,二进制为1001 0100 1101
7,二进制为111
用2381的最高位1001减去111,得10。相当于2381-7*256 = 589 (这个缩小得很快的,所以其实除非除数和被除数非常大,或者超出机器位数,每次操作要多读几遍,肯定会有性能损失)

589 = 刚才的答案10+之前没用过的右边01001101 = 1001001101
再次重复刚才的过程
589的最高位1001减去111,得10。相当于589-7*64 = 141

141 = 刚才的答案10+之前没用过的右边001101 = 10001101
。。。。。
如此循环,最后,当被除数剩1时即为余数

那么商跑到哪里去了呢?
请看二进制除法原理,原理和我这个是一样的,只不过必须控制移位
继续用刚才的例子,2381除以7
以下是不停计算的过程,{}里的是每一次计算的答案,()里的是每一次没参加计算的位

   1001 (0100 1101)             //2381
  -0111                        //7
--------------------------
  {0010}(0100 1101)          //此时0010>0,所以商的最高位为1
  -0011  1                  //这一次不够减,所以商的次高位为0
除数继续右移
   0010 01(00 1101)
  -0001 11
----------------------------
  {0000 10}(00 1101)   //此时000010>0,所以商的第3高位为1
  -0000 11  1         //此时100减111<0,不够减,所以商的第4高位为0


除数继续右移
。。。。。。
如此循环,最后答案为101010100,最前面的1010就是前面四次计算的值。虽然很麻烦,但用电路来实现速度很快。

转载于:https://www.cnblogs.com/suprise/archive/2013/05/19/3086777.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值