模块化逆和BigInteger划分

时间:2010-05-31 03:53:27

标签: java algorithm

我一直在研究计算大整数的模逆的问题,即^ -1 mod n。并一直使用BigInteger的内置函数modInverse来检查我的工作。

我已经按照Menezes等人的“应用密码学手册”中所示对算法进行了编码。对我来说不幸的是,我没有得到所有整数的正确结果。

我的想法是q = a.divide(b)这一行是我的问题,因为除法函数没有很好地记录(IMO)(我的代码也遭受类似的影响)。 BigInteger.divide(val)是圆形还是截断?我的假设是截断,因为文档说它模仿int的行为。任何其他见解都表示赞赏。

这是我一直在使用的代码:

private static BigInteger modInverse(BigInteger a, BigInteger b) throws ArithmeticException {
    //trivial case: b = 0 => a^-1 = 1
    if (b.equals(BigInteger.ZERO)) {
        return BigInteger.ONE;
    }
    //all other cases
    BigInteger x2 = BigInteger.ONE;
    BigInteger x1 = BigInteger.ZERO;
    BigInteger y2 = BigInteger.ZERO;
    BigInteger y1 = BigInteger.ONE;
    BigInteger x, y, q, r;
    while (b.compareTo(BigInteger.ZERO) == 1) {
        q = a.divide(b);
        r = a.subtract(q.multiply(b));
        x = x2.subtract(q.multiply(x1));
        y = y2.subtract(q.multiply(y1));
        a = b;
        b = r;
        x2 = x1;
        x1 = x;
        y2 = y1;
        y1 = y;
    }
    if (!a.equals(BigInteger.ONE))
        throw new ArithmeticException("a and n are not coprime");
    return x2;
}

输出错误输入的示例是:
a:123456789
b:2 ^ 809 - 1

产生预期结果的输入示例是:
a:123456789
b:2 ^ 807 - 1

3 个答案:

答案 0 :(得分:5)

以下是Java语言规范中指定整数除法的方法:

  

JLS 15.17.2 Division Operator

     

整数除法向0舍入。也就是说,为二进制数字提升后的整数操作数nd生成的商是一个整数值{{1}在满足q的同时,其幅度尽可能大;此外,当|d·q|<=|n|q|n|>=|d|具有相同的符号时,n为正,但d和{{1}时q为否定}和|n|>=|d|有相反的符号。

答案 1 :(得分:0)

return x2;更改为return y2;,您的例行程序将给出正确答案。

编辑,此答案不再有效,因为顶级海报更改了他的代码。

答案 2 :(得分:0)

要使代码工作,您需要保存模数的原始值,您可以在开头创建:BigInteger m = b; 然后当你在x2中获得最终结果时,为了避免可能由欧几里德算法产生的负值,计算:x2.add(m),它将是BigInteger a,mod(b)的乘法逆,根据你的代码。