【发布时间】:2018-11-30 15:22:28
【问题描述】:
模逆可以计算如下(来自Rosetta Code):
#include <stdio.h>
int mul_inv(int a, int b)
{
int b0 = b, t, q;
int x0 = 0, x1 = 1;
if (b == 1) return 1;
while (a > 1) {
q = a / b;
t = b, b = a % b, a = t;
t = x0, x0 = x1 - q * x0, x1 = t;
}
if (x1 < 0) x1 += b0;
return x1;
}
但是,如您所见,输入是 ints。上面的代码是否也适用于无符号整数(例如uint64_t)?我的意思是,可以用uint64_t 替换所有int 吗?我可以尝试一些输入,但尝试所有 64 位组合是不可行的。
我对两个方面特别感兴趣:
对于
a和b的值 [0, 2^64),所有计算都不会溢出/下溢(或溢出而无害)吗?(x1 < 0)在未签名的情况下会是什么样子?
【问题讨论】:
-
您的问题已在this blog post 中得到解答。您可以将其写入答案。
-
@user202729 谢谢,这是一篇非常好的文章,但它有一个“模块化”逆的潜在问题。
pX可以小于零,而在模块化设置中则不是,通常的方法是使用if (pX < 0) pX += b。但这是可以(或不能?)溢出的有符号和无符号加法。理想情况下,对于模块化计算,不会有static_cast<S>。但再次感谢您撰写本文,如果您是作者的话。 -
不,我不是作者;但是使用博客文章的作者已经证明的范围来解决您指出的问题并不困难。 (tl;dr: 在您的原始代码中,您知道 x1 的实际值在 [-max(a,b)/2 .. max(a,b)/2] 范围内,所以如果它是负数,那么它必须在 [(uint) -max(a,b)/2 .. UINT_MAX] 范围内并且设置了最高位,您可以检查它是否为真,然后在这种情况下添加 b)。稍后我可能会写一个答案。
标签: math integer-overflow greatest-common-divisor modular-arithmetic