Reputation: 22890
Assume you have 2 positive long
values a
and b
which are greater than 2^32
(and smaller than 2^63
), and an long integer c
.
What is the best way, in java and\or c, to perform operations such as
(a*b)%c
while avoiding arithmetic overflow.
Edit :
c is around 2^34
, and sometimes both a and b are just between 2^32
and c
...
I finally avoided using BigInteger
for the specific situation I was in. Indeed, It was possible to know one divisor of both a
and b
(not always the case), so I would use the arithmetic properties of modulo
to my advantage.
Upvotes: 2
Views: 374
Reputation: 169563
To the best of my knowledge, there's no way to solve your problem without higher precision arithmetics, and at least LLVM's optimizer agrees.
If 128-bit math is not available natively, you'll need to use a general-purpose big integer library, or take the bits you need from a less general implementation like Math128 from GnuCash.
Upvotes: 1
Reputation: 17444
In Java I would use BigInteger:
BigInteger bd = BigInteger.valueOf(2).pow(33);
System.out.println(bd.multiply(bd).remainder(BigInteger.valueOf(2).pow(34).add(BigInteger.valueOf(1))));
Upvotes: 1
Reputation: 76057
You can go even further than what @Oli Charlesworth suggests in his (good) answer. You can decompose in factors a
and b
(not necessary in all the prime factors, a partial decomposition might be enough) and perform the modulus in any intermediate result of the multiplication. Although this is likely to be more costly than going for the bignum, as it will involve quite a few divisions and they are expensive.
Upvotes: 2
Reputation: 272487
Assuming everything's positive, then you can use the following mathematical identity:
(a*b)%c == ((a%c) * (b%c)) % c
Of course, this still doesn't eliminate the possibility of overflow.
The easiest way to completely avoid the issue is to use a big-integer library.
Upvotes: 8