由32整数除法签名64

时间:2009-07-06 21:18:20

标签: integer precision division signed

假设你有一个机器指令udive通过采用(32位被除数&lt;&lt; 32)/ 32bit除数来进行特殊情况64×32无符号除法,我们可以使用以下方法完成64×32除法:< / p>

// assume: a / b guaranteed not to overflow
a = 64bit dividend, a.h & a.l are hi & lo 32bits respectively
b = 32bit divisor

q1 = udive(a.h, b)  // (a.h << 32) / b
r1 = -(q1 * b)      // remainder of the above, shortcut since a.h & 0xffffffff == 0
q2 = a.l / b        // a.l / b using regular unsigned division
r2 = a.l - (q2 * b) // remainder of the above
q = q1 + q2
r = r1 + r2

// r < r2, r overflowed and is >32bits, implies r > b since b is 32bits
// r >= b, quotient too small by 1, adjust
if (r < r2) or (r >= b)
    q = q + 1
return q

然而签名的案件给我带来了麻烦。假设有一个等效的sdive指令执行udive的签名版本,我无法弄清楚如何处理余数等等。

3 个答案:

答案 0 :(得分:0)

我认为如果明确说明哪些变量是32位,那么你的无符号代码会更容易阅读,这些变量是64位以及比较是签名还是无符号。

本书 Hacker's Delight 通常适用于这种低级算术的东西。我目前没有副本,但是64 / 64-> 64给出64 / 32-> 32的代码在线:http://www.hackersdelight.org/HDcode/newCode/divDouble.c

通过简单地获取输入的绝对值,执行无符号除法,然后在输入具有不同符号时翻转结果位的符号来执行已签名的情况。这告诉我,这可能是最好的方法(它肯定比替代方法更容易证明是正确的)。您可能需要特殊情况下,如果红利不会在洗涤中失效,则红利是最小可能的整数。

答案 1 :(得分:0)

感谢您的回答。我看过Hacker's Delight。如果你看看HD中的divdi3函数,当除数为32位时,会调用DIVS,即64 / 32-> 32指令,并且结果已知不会溢出。我所在的机器没有通用的64 / 32-> 32指令,它有上面提到的特殊情况。 64 / 32-> 32的上述函数是我在无符号情况下对DIVU的实现,所以我正在尝试为DIVS编写类似的东西。

我可以忘记DIVS路径,但这是绝大多数常见的情况,我想尽可能多地点击它,这只是一个棘手的实现。

对于不清楚的伪代码感到抱歉,但一切都是无符号的,大部分是32位。

DIVU(uint64 a, uint32 b) {
// assume: a / b guaranteed not to overflow
// a = 64bit dividend, a.h & a.l are hi & lo 32bits respectively
// b = 32bit divisor

uint32 q1 = udive(a.h, b)      // (a.h << 32) / b
uint32 r1 = -(q1 * b)          // remainder of the above, shortcut for (a.h << 32) - (q1 * b) since (a.h << 32) & 0xffffffff == 0
uint32 q2 = a.l / b            // a.l / b using regular unsigned division
uint32 r2 = a.l - (q2 * b)     // remainder of the above
uint32 q = q1 + q2
uint32 r = r1 + r2

// r < r2, r overflowed and is >32bits, implies r > b since b is 32bits
// r >= b, quotient too small by 1, adjust
if (r < r2) or (r >= b)
        q = q + 1
return q
}

答案 2 :(得分:0)

你可以忽略divdi3调用div的特殊优化情况;我想提请注意的事实是,当divdi3需要进行全强度除法时,它通过调用udivdi3而不是通过使用等效于udivdi3算法的有符号除法来实现它。

看看Knuth vol 2我看到他也基本上说你通过取绝对值,做无符号除法然后修复符号位的过程来进行符号划分。这对我来说很直观,因为带符号的2s补码不具有无符号数的a ==(ah * 2 ^ 32)+ al的方便属性,因此通过操作组装64位操作并不容易分别是两半。

前后摆弄不应该是无符号划分的额外周期......

PS:无论如何,CPU是什么怪话? : - )