我只能想到
a.mod(n).multiply(b.mod(n)).mod(n)
而且您似乎已经意识到这一点。
BigInteger 有一个toByteArray(),但在内部使用了ints。因此 n 必须非常大才能产生影响。也许在密钥生成密码代码中可能会有这样的工作。
此外,如果您考虑缩短乘法,您将得到如下结果:
public static BigInteger multiply(BigInteger a, BigInteger b, int mod) {
if (a.signum() == -1) {
return multiply(a.negate(), b, mod).negate();
}
if (b.signum() == -1) {
return multiply(a, b.negate(), mod).negate();
}
int n = (Integer.bitCount(mod - 1) + 7) / 8; // mod in bytes.
byte[] aa = a.toByteArray(); // Highest byte at [0] !!
int na = Math.min(n, aa.length); // Heuristic.
byte[] bb = b.toByteArray();
int nb = Math.min(n, bb.length); // Heuristic.
byte[] prod = new byte[n];
for (int ia = 0; ia < na; ++ia) {
int m = ia + nb >= n ? n - ia - 1 : nb; // Heuristic.
for (int ib = 0; ib < m; ++ib) {
int p = (0xFF & aa[aa.length - 1 - ia]) * (0xFF & bb[bb.length - 1 - ib]);
addByte(prod, ia + ib, p & 0xFF);
if (ia + ib + 1 < n) {
addByte(prod, ia + ib + 1, (p >> 8) & 0xFF);
}
}
}
// Still need to do an expensive mod:
return new BigInteger(prod).mod(BigInteger.valueOf(mod));
}
private static void addByte(byte[] prod, int i, int value) {
while (value != 0 && i < prod.length) {
value += prod[prod.length - 1 - i] & 0xFF;
prod[prod.length - 1 - i] = (byte) value;
value >>= 8;
++i;
}
}
那段代码看起来并不诱人。 BigInteger 的问题是仅将内部值公开为 big-endian byte[],其中第一个字节是最重要的字节。
如果数字以 N 为底会更好。这不是不可想象的:如果 N 是 2 的幂,那么一些不错的优化是可行的。
(顺便说一句,代码未经测试 - 因为它似乎没有令人信服的更快。)