如何解决无符号除法算法中的溢出检测
我有一个关于 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 举报,一经查实,本站将立刻删除。