C中的定点无符号除法

Posted

技术标签:

【中文标题】C中的定点无符号除法【英文标题】:Fixed-point unsigned division in C 【发布时间】:2011-12-14 14:43:18 【问题描述】:

我需要一个算法来在 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 

【问题讨论】:

我不明白这个问题。您能否提供示例输入以及预期和实际输出。 如果你想除以无符号值,你至少可以在你的函数声明中这样说。 您的代码看起来不像处理被零除或溢出。例如,如果你将 4 除以 0.25,就会出现问题。 @David Hefferman 是的。这是家庭作业。但至少我正在努力做到这一点。 @unwind 很抱歉。在我将要使用的应用程序中,它必须是这样的,我只是粘贴了我编写的代码。我会编辑它。 【参考方案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&lt;&lt;14) = 0x0c000000

这样做确实会损失一些精度,但如果不使用更大的分子,这是不可避免的。例如 5.0/3.0 = 1.66667 = 0x1AAAAAA [4.28],但是((5.0&lt;&lt;28)/(3&lt;&lt;14))&lt;&lt;14 = 0x1AAA8000 [4.28] = 1.66662

【讨论】:

我想还是按我的方式做比较好。整数部分不使用 5 位的目的是避免精度损失,您算法的损失大于我的 1 位。 你的更准确,它也很慢。定点的通常动机是具有慢浮点数学的处理器上的速度。但如果你想要准确性,你的方法是最好的。我认为至少丢失一位是不可避免的。【参考方案2】:

正如here 指出的那样(示例:将整数乘以常数的倒数),您可以通过乘以倒数来重新实现除法。之后你应该可以用 4 位来表示整数部分。

【讨论】:

您的链接是否使用全精度执行逆和乘法?在这种情况下,这将不起作用 - 您的方法将“正确”答案四舍五入,而不是执行定点除法。这两种方法通常会给出不同的结果。

以上是关于C中的定点无符号除法的主要内容,如果未能解决你的问题,请参考以下文章

逆向课程第五讲逆向中的优化方式,除法原理,以及除法优化下

汇编有符号除法运算

有符号和无符号之间的减法,然后是除法

数据的表示和运算-第一节3:无符号数的表示和运算

位运算乘除法

无符号与有符号整数的性能