整数乘以有理数,没有中间溢出
Multiplying integer by rational without intermediate overflow
我有一个表示非负有理数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,但它似乎没有提供此功能)
你可以使用农民乘法:
// 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;
}
要么128位,要么使用Karatsuba乘法;或者你可以用中国的余数定理来表示(n * r.p)模p1和模p2。
相关文章:
- 2D数组来自文本输入,中间有空格
- 'short int'持有的值溢出,但"自动"不会溢出?
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- 大于65535的C++数组[size]引发不一致的溢出
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- C++中无符号字符溢出
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 我的 int main() 中出现堆栈溢出错误
- 整数溢出,最大值为 pow(10,19)
- 获取隐式转换溢出从无符号到已签名的警告
- 使用 strcat 获取缓冲区溢出错误
- LeetCode 1:两和 - 地址清理器:堆缓冲区溢出地址
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 递归形成字符串中所有数字字符的中间和?
- C++ 对象数组堆栈溢出
- 使用提升::lexical_cast捕获溢出
- C++ Unordered_set功能中的溢出
- 链表错误的中间
- 如果表达式的中间结果溢出,这是未定义的行为吗
- 整数乘以有理数,没有中间溢出