BigInteger 用 BigInteger 取幂:ArithmeticException,会溢出支持的范围

问题描述

我正在构建 DSA 算法。但是我在将 BigInteger 数字与其他 BigInteger 数字进行排名时遇到了问题。这是我要使用的公式:

<dimen name="line">2.6dp</dimen>

这是我制作的代码

v = ((g^u1 * y^u2) mod p) mod q

运行脚本时,报错为:

BigInteger v = g.pow(u1.intValue()).multiply(y.pow(u2.intValue())).mod(p).mod(q);

解决方法

为了扩展我的评论,因为我找不到重复的:使用 modPow

这里的问题是 g^u1(和 y^u2)真的很大。但是很多时候在处理数学中的幂时,你会在它后面有一个 mod 语句,这简化了很多:通常 a ^ b mod c 可以表示为 ((((a * a) mod c) * a) mod c) * a) mod c ..... (b 次)。这基本上就是 modPow 所做的,它在推导过程中应用 mod。这将返回相同的数字但不会溢出。它们在数学上是相同的,但可以通过计算机通过合理的努力来计算,而另一个则不能。作为开发人员,您需要聪明地以计算机可以正确处理的方式简化或重新表述您想要解决的表达式。

BigInteger v = g.modPow(u1,p).multiply(y.modPow(u2,p)).mod(p).mod(q);

基本上要计算 (6 ^ 10 mod 7),您永远不想先计算 6 ^ 10 然后应用 mod 7 而是执行 6 * 6 mod 7 = 36 mod 7 = 1 => 1 * 6 mod 7 = 6 => 6 * 6 mod 7 = 36 mod 7 = 1 => ...,您可以看到您唯一的值处理的是 1 和 6 而不是 60466176(即 6^10)。