无符号除法算法中的溢出检测

问题描述

我有一个关于 64/32 位除法算法的问题,它出现在 Hacker's Delight 的第 9-4 章无符号长除法中,图 9-3,“div1u”。网上可以看到here,我复制粘贴如下:

unsigned divlu2(unsigned u1,unsigned u0,unsigned v,unsigned *r) {
   const unsigned b = 65536; // Number base (16 bits).
   unsigned un1,un0,// Norm. dividend LSD's.
            vn1,vn0,// Norm. divisor digits.
            q1,q0,// Quotient digits.
            un32,un21,un10,// Dividend digit pairs.
            rhat;            // A remainder.
   int s;                    // Shift amount for norm.

   if (u1 >= v) {            // If overflow,set rem.
      if (r != NULL)         // to an impossible value,*r = 0xFFFFFFFF;    // and return the largest
      return 0xFFFFFFFF;}    // possible quotient.

   s = nlz(v);               // 0 <= s <= 31.
   v = v << s;               // Normalize divisor.
   vn1 = v >> 16;            // Break divisor up into
   vn0 = v & 0xFFFF;         // two 16-bit digits.

   un32 = (u1 << s) | (u0 >> 32 - s) & (-s >> 31);
   un10 = u0 << s;           // Shift dividend left.

   un1 = un10 >> 16;         // Break right half of
   un0 = un10 & 0xFFFF;      // dividend into two digits.

   q1 = un32/vn1;            // Compute the first
   rhat = un32 - q1*vn1;     // quotient digit,q1.
again1:
   if (q1 >= b || q1*vn0 > b*rhat + un1) {
     q1 = q1 - 1;
     rhat = rhat + vn1;
     if (rhat < b) goto again1;}

   un21 = un32*b + un1 - q1*v;  // Multiply and subtract.

   q0 = un21/vn1;            // Compute the second
   rhat = un21 - q0*vn1;     // quotient digit,q0.
again2:
   if (q0 >= b || q0*vn0 > b*rhat + un0) {
     q0 = q0 - 1;
     rhat = rhat + vn1;
     if (rhat < b) goto again2;}

   if (r != NULL)            // If remainder is wanted,*r = (un21*b + un0 - q0*v) >> s;     // return it.
   return q1*b + q0;
}

具体来说,我对变量 un21 的边界感兴趣。它可以有多大?有点令人惊讶的是,它可以比 v 大,但要大多少?

换句话说,在 again2 下有测试 q0 >= b。如果我想知道除法 (q0 = un21/vn1) 最终是否溢出,测试 (un21 >> 16) == vn1 是否足够,还是必须读取 (un21 >> 16) >= vn1 而不是 if q0 >= b?>

这个想法是在计算商之前提前知道除法是否溢出。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...