我有一个表示非负有理数p / q的结构:
struct rational {
uint64_t p;
uint64_t q; // invariant: always > 0
};
我想将我的理性乘以uint64 n
并得到一个整数结果,向下舍入。也就是说,我想计算:
uint64_t m = (n * r.p)/r.q;
同时避免n * r.p
中的中间溢出。 (当然最终结果可能会溢出,这是可以接受的。)
我该怎么做?有没有办法在没有高倍数的情况下做到这一点?
(我查看了boost :: rational但它似乎没有提供此功能。)
答案 0 :(得分:1)
您可以使用peasant multiplication:
// 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;
}
答案 1 :(得分:0)
128位,你可以在那里使用Karatsuba乘法;或者你可以使用中国剩余定理来表示(n * r.p)mod p1和mod p2。第二个可能会慢一些。