I don't want the nightmare of installing GMP on Windows.
I have two numbers A and B, unsigned long long
s, on the order of magnitude 10^10 or so at most, but even when doing ((A%M)*(B%M))%M
, I get integer overflow.
Are there homebrew functions for calculating (A*B)%M
for larger numbers?
We can multiply recursively to overcome the difficulty of overflow. To multiply a*b, first calculate a*b/2 then add it twice. For calculating a*b/2 calculate a*b/4 and so on (similar to log n exponentiation algorithm).
One very good way to prevent integer overflows is to use int64_t to implement integers. In most case, 64-bits ints will not commit overflow, unlike their 32-bits counterparts. There is actually very few downsides in using int64_t instead of int32_t .
Therefore, unsigned overflow results from any operation that crosses the divide between 2N-1 and 0. Stated more plainly, if performing addition (which should make the result larger) produces a smaller result, the addition caused unsigned overflow.
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
If the modulus M
is sufficiently smaller than ULLONG_MAX
(which is the case if it's in the region of 10^10), you can do it in three steps by splitting one of the factors in two parts. I assume that A < M
and B < M
, and M < 2^42
.
// split A into to parts
unsigned long long a1 = (A >> 21), a2 = A & ((1ull << 21) - 1);
unsigned long long temp = (a1 * B) % M; // doesn't overflow under the assumptions
temp = (temp << 21) % M; // this neither
temp += (a2*B) % M; // nor this
return temp % M;
For larger values, you can split the factor in three parts, but if the modulus becomes really close to ULLONG_MAX
it becomes ugly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With