假设你有一个机器指令udive,通过采取一(32位股息<< 32)/ 32位除数由32无符号除法做了特殊情况下64,我们可以使用下面做一个完整的64×32师:
// 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的签名版本,我不能完全解决如何处理余和诸如此类的东西。
我觉得你的未签名代码会更容易阅读,如果它是明确了解哪些变量是32位,这是64位和比较是否带符号。
这本书黑客的喜悦一般为这种低级别的运算东西好。 我没有副本的时刻出手,但其做64 / 64-> 64给出的64 / 32-> 32码在线: http://www.hackersdelight.org/HDcode/newCode/divDouble。 C
通过简单地把输入端的绝对值,做一个无符号除法,然后翻转结果位的符号,如果输入有不同的标志确实签署的情况。 这表明,我认为这可能是最好的方法(这当然更容易证明比选择正确的)。 您可能需要特殊的情况下,股息为最小可能的整数,如果它不只是掉下来的洗。
谢谢回答。 我已经看了黑客的喜悦。 如果你看一下在高清divdi3功能有到DIVS一个电话,64 / 32-> 32个指令,当除数为32位,结果被称为不溢出。 我在机器没有通用64 / 32-> 32个指令,它具有上述的特殊情况。 64 / 32-> 32以上的功能是我实现在无符号的情况下DIVU,所以我试图制定出DIVS类似的东西。
我可以忘掉的div路径,但是这是绝大多数常见的情况,我想尽可能多地打它,它只是一个棘手的实现。
对不起,我不清楚伪代码,但一切是无符号的,大多是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
}
你可以忽略调用的div divdi3的特殊优化案例; 我想提请注意的事情是事实,当divdi3需要做全强度划分它通过调用udivdi3而不是由具有签署分相当于udivdi3算法做的。
展望克努特第2卷我看得出来,他也基本上是说你就按取绝对值,做一个无符号除法,然后再把固定了符号位的过程中签署的划分。 这使得直观的感觉对我来说,因为签署二进制补码数字不具有便捷的特性,一个==(啊* 2 ^ 32)+人是无符号数做,所以它不是那么容易通过操作上装配的64位运算分开的两半。
在之前和之后摆弄不应该是在无符号除法许多额外的周期...
PS:什么怪人CPU是这样的啊? :-)