【问题标题】:Java BigInteger modInverse and modPowJava BigInteger modInverse 和 modPow
【发布时间】:2016-12-14 08:23:49
【问题描述】:

我正在尝试了解 Java 的 BigInteger 类的 modPow 和 modInverse 的行为,因为它们不能像我预期的那样工作。也许我遗漏了一些简单的东西,所以这里有一段非常简单的代码:

BigInteger a = BigInteger.valueOf(2);
BigInteger b = BigInteger.valueOf(5);

BigInteger n1 = new BigInteger(32, 100, new SecureRandom());
System.out.println("n = " + n1);

System.out.println("a^b = " + a.modPow(b, n1) + " ;; (a^b)^(b^-1) = " + a.modPow(b, n1).modPow(b.modInverse(n1), n1));

我得到的输出是:

n = 2664021049    (This is a random prime, can change each run)
a^b = 32 ;; (a^b)^(b^-1) = 4

现在,我希望最后一行的42,因为它是(a^b)^(1/b) = a^(b*(1/b)) = a

这也应该在模域中工作吗?

我做错了什么?

【问题讨论】:

  • (a^b)^(1/b) = a^(b*(1/b)) - 这不适用于模逆。
  • 那么有没有另一种方法可以给出(a^b)b 我找到a

标签: java biginteger modulo


【解决方案1】:

简答:反转 b mod p-1,而不是 mod p。 (如果b不是可逆模p-1,则问题无法解决。)


虽然如果x ≡ y (mod p),然后x^z ≡ y^z (mod p),我们不能得出结论z^x ≡ z^y (mod p)。例如,根据费马小定理,

x^p ≡ x (mod p)

即使p ≡ 0 (mod p)x^0 = 1

然而,费马小定理给了我们一个解决方案。对于整数 xy 以及素数模数 p,如果我们可以找到 y 的乘法逆 z mod p-1,那么

(x^y)^z = x^(yz)
        = x^(k(p-1) + 1) for some k
        = (x^(p-1))^k * x

如果x ≡ 0 (mod p),那么(x^(p-1))^k * x ≡ x (mod p),因为两边都等于0。

如果x !≡ 0 (mod p),那么我们可以从x^p ≡ x (mod p)派生x^(p-1) ≡ 1 (mod p),我们就有(x^(p-1))^k * x ≡ 1^k * x ≡ x (mod p)

因此,(x^y)^z ≡ x (mod p)

另一方面,如果y 不是可逆模p-1,那么我们无法从x^y 恢复x,因为有多个可能的x 值。例如,对于x = 2, y = 3, p = 7,我们有x^y ≡ 1 (mod p),但x 可能是1

【讨论】:

    【解决方案2】:

    我猜困惑来自于,那个

    b.modInverse(n1) == 532804210
    

    因为(5 * 532804210) mod 2664021049 == 1

    之后:

    a.modPow(b, n1) == 32
    

    => 32 ^ b.modInverse(n1) mod 2664021049

    => 32 ^ 532804210 模 2664021049 == 4

    【讨论】:

      【解决方案3】:

      参考这里了解 BigInteger 类的 modPow() 和 modInverse() 的行为。

      modPow:

      BigInteger numOne = new BigInteger("5");
      BigInteger numTwo = new BigInteger("20");
      BigInteger exponent = new BigInteger("3");
      BigInteger MP = numOne.modPow(exponent, numTwo);
      System.out.println(numOne + " ^ " + exponent + " mod " + numTwo + " = " + MP);
      

      modInverse:

      BigInteger numOne = new BigInteger("7");
      BigInteger numTwo = new BigInteger("20");
      BigInteger MI = numOne.modInverse(numTwo);
      System.out.println(numOne + " ^-1 mod " + numTwo + " = " + MI);
      

      【讨论】:

        猜你喜欢
        • 2013-05-11
        • 2020-09-17
        • 1970-01-01
        • 1970-01-01
        • 2011-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-13
        相关资源
        最近更新 更多