2011-12-14 67 views
2

我需要一个算法来做C中的无符号定点除法。我最多可以使用32位字。定点无符号除法C

我想尽量减少表示整数部分所需的位数,同时可以使用[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; 
} 

如果你有一个解决方案,但不想了解代码,请发布它。 :)

例子:

我们希望在2,这将导致0.75分1.5。假设我们使用整数部分的4位和分数的28位。所以,我们的数字是十六进制是:

1.5: 0x18000000 
2:  0x20000000 
result: 0x0c000000 
+0

这气味像功课 – 2011-12-14 14:47:06

+2

我不明白的问题。你能提供一个示例输入,以及预期的和实际的输出。 – 2011-12-14 14:55:03

+1

如果你想分解无符号的值,你能做的最少就是在你的函数声明中这么说。 – unwind 2011-12-14 15:12:38

回答

1

正如指出的here(例如:乘以一个常数的倒数的整数),那么您可以使用倒数乘法重新实现你的部门。之后,您应该能够用4位来表示整数部分。

0

你有4.28定点数,你想除以4.28的数字。您可以通过从分母中减去分子的精度来找到除法后的精度,因此直分可以得到4.28-4.28 = 0--无有效位。显然这是行不通的。

 1.5 [4.28] 0x18000000 
/2.0 [4.28] 0x20000000 
    = 0? [0.00] 0x00000000 

做这将是(由2^28相乘),然后做一个64位鸿沟,促进分子以8.56的理想方法:

     . . . . 
    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