7

我有一个表示非负有理数 p/q 的结构:

struct rational {
    uint64_t p;
    uint64_t q; // invariant: always > 0
};

我想将我的有理数乘以 uint64n并得到一个整数结果,四舍五入。也就是说,我想计算:

uint64_t m = (n * r.p)/r.q;

同时避免n * r.p. (当然最终结果可能会溢出,这是可以接受的。)

我怎样才能做到这一点?有没有办法在没有高倍数的情况下做到这一点?

(我查看了 boost::rational 但它似乎没有提供此功能。)

4

2 回答 2

1

您可以使用农夫乘法

// requires 0 < c < 2^63
// returns (a * b) / c.
uint64_t multDiv(uint64_t a, uint64_t b, uint64_t c) {
  uint64_t rem = 0;
  uint64_t res = (a / c) * b;
  a = a % c;
  // invariant: a_orig * b_orig = (res * c + rem) + a * b
  // a < c, rem < c.
  while (b != 0) {
    if (b & 1) {
      rem += a;
      if (rem >= c) {
        rem -= c;
        res++;
      }
    }
    b /= 2;
    a *= 2;
    if (a >= c) {
      a -= c;
      res += b;
    }
  }
  return res;
}
于 2016-08-12T20:31:59.087 回答
0

无论是 128 位,您都可以在那里使用Karatsuba乘法;或者您可以使用中国剩余定理来表示 (n * rp) mod p1 和 mod p2。第二个可能会慢一些。

于 2016-08-12T19:57:56.697 回答