Java 用%处理溢出

Java 用%处理溢出,java,overflow,long-integer,biginteger,modulo,Java,Overflow,Long Integer,Biginteger,Modulo,我有一个Java函数,它如下所示: private static long fieldPrime = 4294967291L; // 2^32-5 public final static long modMult(long a, long b) { long r = (a*b) % fieldPrime; return r; } 它将两个值相乘(保证介于0和2^32-5之间),然后对大素数进行模化 它适用于大多数数字,但有时a*b溢出,这会导致函数返回错误的值。

我有一个Java函数,它如下所示:

private static long fieldPrime = 4294967291L; // 2^32-5
public final static long modMult(long a, long b) {
    long r = (a*b) % fieldPrime;        
    return r;
}
它将两个值相乘(保证介于0和2^32-5之间),然后对大素数进行模化


它适用于大多数数字,但有时a*b溢出,这会导致函数返回错误的值。不幸的是,Java不支持无符号long(这本可以解决这个问题),而BigInteger速度太慢。我能用别的方法解决这个问题吗?也就是说,当我检测到溢出时,我是否可以以某种方式调整r(在这种情况下,a*b<0总是意味着它溢出)。

一旦知道自己再次处于安全范围内(模后),您可以将a、b和fieldPrime转换为双精度,并将结果转换回长精度。但是,在某些情况下,双精度可能会导致舍入错误

除此之外,我想说BigInteger是您最好的选择,如果它太慢,也许您可以制作一些可以使用字节数组而不是long的东西,但我怀疑这会快得多。

这应该有效(如果a和b都在0和fieldPrime-1之间):

当发生溢出时,a*b实际上是a*b-2^64,因此需要添加(2^64 mod fieldPrime)。需要再添加一个fieldPrime和一个%运算,以使结果在0到fieldPrime-1的范围内(否则可能为负值)

(如果fieldPrime>2^32,则不会以这种方式工作。)

编辑 else部分也可以更改为:

    return (fieldPrime-a)*(fieldPrime-b)%fieldPrime;

(我不知道哪一个更快。)

如果你要否决我的答案,至少要尽力帮助我,你可能应该告诉我为什么要给我一个检查的机会……我没有否决。我同意你的看法,否决票之后应该发表评论。
    return (fieldPrime-a)*(fieldPrime-b)%fieldPrime;