我需要一个算法在C中进行无符号定点除法。我最多可以使用32位字。
我希望最小化表示整数部分所需的位数,同时能够使用[0..15]范围内的数字。显然,最小位数是4.问题是我提出的算法只能使用5位。因为它将余数与除数进行比较然后移动余数直到它大于除数,如果除数具有最高有效位1,那么算法除了移动余数之外什么都不做(它永远不会更大)。这是代码:
int divu(int a, int b){
int pt_int, r, pt_frac=0;
int i;
pt_int = ((unsigned) a/b) << BITS_FRAC;
r = (unsigned) a%b;
for (i=BITS_FRAC; i>=0; i--){
if ((unsigned) r < b)
r <<= 1;
else{
r -= b;
pt_frac += 01 << i;
r <<= 1;
}
}
return pt_int + pt_frac;
}
如果您确实有解决方案,但又不想理解代码,请发布。 :)
示例:
我们希望将1.5除以2,结果为0.75。假设我们使用4位作为整数部分,使用28位作为分数。所以我们的数字是十六进制是:
1.5: 0x18000000
2: 0x20000000
result: 0x0c000000
答案 0 :(得分:1)
正如所指出的here(例如:用常数的倒数乘以整数),你可以通过乘以倒数来重新实现你的除法。之后,您应该能够用4位表示整数部分。
答案 1 :(得分:1)
你有一个4.28的固定点数,你想要除以4.28的数字。您可以通过从分母中减去分子的精度来找到除法后的精度,因此直线除法将给出4.28 - 4.28 = 0 - 无有效位。显然这不起作用。
1.5 [4.28] 0x18000000
/ 2.0 [4.28] 0x20000000
= 0? [0.00] 0x00000000
理想的方法是将分子提升到8.56(乘以2 ^ 28),然后进行64位除法:
. . . .
1.5 [8.56] 0x180000000000000
/ 2.0 [4.28] 0x20000000
= 0.75 [4.28] 0x0c000000
如果你真的不能使用64位数字,那么你唯一的选择就是减少分母。 例如,您可以通过除以2 ^ 14
来使用精度的一半 1.5 [4.28] 0x18000000
/ 2.0 [2.14] 0x8000
= 0.75 [2.14] 0x3000
然后,您可以将结果乘以相同的因子,以返回到4.28数字:0x3000 *(1<<14) = 0x0c000000
你确实以这种方式失去了一些精确度,但如果不使用更大的分子,这是不可避免的。例如
5.0/3.0 = 1.66667 = 0x1AAAAAA [4.28]
,但是
((5.0<<28)/(3<<14))<<14 = 0x1AAA8000 [4.28] = 1.66662