32位处理器上的64位/ 64位余数查找算法?

时间:2017-05-23 07:40:46

标签: c algorithm arm integer-division eabi

我知道过去曾经问过类似的问题,但是经过漫长的过程后我已经实现了通过重复减法方法正确地找到的算法。但我无法从这种方法中找出余数。有没有快速简便的方法可以在32位处理器上找到64位/ 64位分区的余数。更确切地说,我正在努力实施

ulldiv_t __aeabi_uldivmod(  
 unsigned long long n, unsigned long long d)  

在本文件http://infocenter.arm.com/help/topic/com.arm.doc.ihi0043d/IHI0043D_rtabi.pdf

中引用

2 个答案:

答案 0 :(得分:1)

什么?如果你做了重复的减法(这听起来很基本),那么当你不能做另一次减法时,剩下的就不是你所留下的那么简单吗?

至少这是一种天真直观的方式:

DynamicProperties

或者我在这里错过了船?

当然,对于大数字来说,这将是非常缓慢的,但这是重复减法。我敢肯定(即使没有看!)还有更高级的算法。

答案 1 :(得分:1)

这是一种除法算法,在O(log(n / d))

中运行
uint64_t slow_division(uint64_t n, uint64_t d)
{
   uint64_t i = d;
   uint64_t q = 0;
   uint64_t r = n;
   while (n > i && (i >> 63) == 0) i <<= 1;
   while (i >= d) {
      q <<= 1;
      if (r >= i) { r -= i; q += 1; }
      i >>= 1;
   }
   // quotient is q, remainder is r 
   return q;    // return r 
}
如果只需要r(余数),则可以删除

q(商)。您可以将每个中间变量i,q,r实现为一对uint32_t,例如i_lo,i_hi,q_lo,q_hi ..... shift,add和subt lo和hi是简单的操作。

#define left_shift1 (a_hi, a_lo)          // a <<= 1    
{
    a_hi = (a_hi << 1) | (a_lo  >> 31)
    a_lo = (a_lo << 1) 
}

#define subtraction (a_hi, a_lo, b_hi, b_lo)    // a-= b    
{
    uint32_t t = a_lo
    a_lo -= b_lo
    t = (a_lo > t)        // borrow
    a_hi -= b_hi + t
}   

#define right_shift63 (a_hi, a_lo)      // a >> 63
{
   a_lo = a_hi >> 31;
   a_hi = 0;
}

等等。

0因为除数仍然是一个尚未解决的挑战:-)。