Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling overflow with %

I have a function Java which looks like this:

private static long fieldPrime = 4294967291L; // 2^32-5
public final static long modMult(long a, long b) {
    long r = (a*b) % fieldPrime;        
    return r;
}

It multiplies two values (which are guaranteed to be between 0 and 2^32-5) and then does modulo a large prime.

It works for most numbers but sometimes a*b overflows and this causes the function to return the wrong value. Unfortunately Java doesn't support unsigned longs (which would have solved the issue) and BigInteger is too slow. Can I solve this some other way? I.e. can I adjust r somehow when I detect overflow (in this case a*b < 0 always means it has overflowed).

like image 985
Yrlec Avatar asked Feb 17 '26 13:02

Yrlec


1 Answers

This should work (if both a and b are between 0 and fieldPrime-1):

  private static long fieldPrime = 4294967291L; // 2^32-5
  private static long correctionFactor = fieldPrime+25; //fieldPrime + (2^64) mod fieldPrime 

  public final static long modMult(long a, long b) {
      long r = (a*b);
      if (r>=0)
      {
        return r % fieldPrime;
      }
      else
      {
        return ((r% fieldPrime)+correctionFactor)%fieldPrime;  
      }
  }

When overflow occurs a*b will actually be a * b - 2^64 so adding (2^64 mod fieldPrime) is what is needed. Adding one more fieldPrime and one more % operation is needed to make the result in range 0 to fieldPrime-1 (otherwise it may be negative).

(It won't work this way if fieldPrime>2^32.)

EDIT The else part can also be changed to:

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

(I don't known which is faster.)

like image 183
x22 Avatar answered Feb 19 '26 01:02

x22



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!