【问题标题】:64 bit / 64 bit remainder finding algorithm on a 32 bit processor?32 位处理器上的 64 位/64 位余数查找算法?
【发布时间】:2017-05-23 07:40:45
【问题描述】:

我知道过去有人问过类似的问题,但经过漫长的过程,我已经实现了算法,以使用重复减法除法正确找到 。但我无法从这种方法中找出余数。有什么快速简便的方法可以在 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

【问题讨论】:

标签: c algorithm arm integer-division eabi


【解决方案1】:

什么?如果你做重复减法(这听起来很基础),那么当你不能再做一次减法时,剩下的不是余数那么简单吗?

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

uint64_t simple_divmod(uint64_t n, uint64_t d)
{
  if (n == 0 || d == 0)
    return 0;
  uint64_t q = 0;
  while (n >= d)
  {
    ++q;
    n -= d;
  }
  return n;
}

还是我错过了船,在这里?

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

【讨论】:

  • 实际情况,例如最坏情况下的执行时间(即使忽略 d==0 情况)?
  • 非常感谢,看到需要的重复位移并获得正确的结果,我不知所措。我正在做稳健性,我的输入分子“18446744073709551615”不适合计算器,它被四舍五入为 18446744073709551611,因此我的结果也出错了。我没有想到这一点。
  • while (n >= d) 更正确,仍然不切实际的实现
【解决方案2】:

这是一个除法算法,运行时间为 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 .....移位、加减 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 作为除数仍然是一个未解决的挑战:-)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 2012-07-25
    • 2010-09-19
    • 2013-02-23
    • 2018-09-28
    • 2014-05-27
    相关资源
    最近更新 更多