p.g*_*.g. 9 c algorithm biginteger division bignum
我需要计算
result = (dividend * factor) / divisor
Run Code Online (Sandbox Code Playgroud)
哪里
dividend: full range of int64_t values
factor: either a full range of uint32_t values or as a special case 2^32
divisor: positive values of int64_t
result: is guaranteed to fit in a int32_t
Run Code Online (Sandbox Code Playgroud)
我需要在没有微控制器上的任何库的普通C/C++中执行此操作.编译器支持int64_t和uint64_t类型; 很可能没有用于乘法或除法的硬件实现.目前我有uint32_t因子的解决方法,但我需要因子2 ^ 32的解决方案.
OP:“目前我有针对 uint32_t 因素的解决方法”
这factor == 2^32是一个极端情况,并且是这里需要解决的所有问题,因为 OP 的“解决方法”可以处理这些因素[0 ... 2^32-1]。
如果dividend可以加倍而不会溢出,则可以简单地使用factor == 2^31加倍的 dividend。
如果divisor是偶数,则使用factor == 2^31减半divisor。 @风向标
不然dividend就大了。回想一下,商是在[-2^31 ... 2^31-1]范围内的。一般来说,大dividend和factor == 2^32被除数的乘积divisor会超出int32_t范围,因此那些超出范围的组合不值得关注,因为“结果:保证适合int32_t”。
可接受的边缘条件出现时最终商接近范围的边缘int32_t。
pow(2,63) == 9223372036854775808
pow(2,62) == 4611686018427387904
pow(2,32) == 4294967296
pow(2,31) == 2147483648
Smallest Dividends Factor Largest Divisors Smallest Quotients
-4611686018427387905 4294967296 -9223372036854775807 2147483648.00+
-4611686018427387905 4294967296 9223372036854775807 -2147483648.00+ OK
4611686018427387904 4294967296 -9223372036854775807 -2147483648.00+ OK
4611686018427387904 4294967296 9223372036854775807 2147483648.00+
Run Code Online (Sandbox Code Playgroud)
经过测试,dividend和 是divisor中唯一可代表的答案INT32_MIN。
示例代码:
int32_t muldiv64(int64_t dividend, uint64_t factor, int64_t divisor) {
if (factor >= 0x100000000) {
assert(factor == 0x100000000);
factor /= 2;
if (dividend >= INT64_MIN/2 && dividend <= INT64_MAX/2) {
dividend *= 2;
} else if (divisor %2 == 0) {
divisor /= 2;
} else {
return INT32_MIN;
}
}
return workaround_for_the_uint32_t_factor(dividend, factor, divisor);
}
Run Code Online (Sandbox Code Playgroud)
最初的问题是检测这个边缘条件以及如何处理它。 workaround_for_the_uint32_t_factor()可能还没有编码,因此没有发布。