Even though end results of terms like $123456789^{987654321} \mod 4321$ are relatively small, calculating them with regular power functions will likely fail, since the modulo operator isn't taken into account. A way to avoid this, is using "exponentiation by squaring": Assuming three integers bigger 1 $x,p,m$, the following statement holds true:
$$x^p\mod m=
\begin{cases}
\left(x^{p/2}\mod m\right)^2\mod m, & \text{for }p\text{ even,}\\
\left(x\cdot \left(x^{p-1}\mod m\right)\right)\mod m, & \text{for }p\text{ odd.}
\end{cases}
$$
Repeated application of this rule allows safe exponentiation with large exponents.
The following function applies this method recursively for integers of type long long
. Since long long
is a 64bit integer, any base or modulo value bigger than $\sqrt{2^{63}-1}\approx 3\cdot 10^9$ still poses a risk for an integer overflow. To avoid this issue altogether, numeric data types of unlimited size could be used.
Download(zip).
//Knowledgedump.org - Function for modular exponentiation by squaring, to reduce integer overflows. #ifndef MODULAR_EXP_H //Include guard #define MODULAR_EXP_H #include <iostream> //Forward declaration //Function for checking input arguments. long long modular_exp(long long base, long long exp, long long mod); //Recursive function for calculation. long long mod_exp(long long base, long long exp, long long mod); //Function only allows exponent bigger or equal 0, since integer types are used. //Checks input, then calls the actually calculating function. long long modular_exp(long long base, long long exp, long long mod) { if (base == 0) { return 0; } if (base == 1) { return 1; } if (exp == 0) { return 1; } if (exp < 0) { std::cout << "Invalid exponent input." << std::endl; return 0; } if ((mod == 0) || (mod == 1) || (mod == -1)) { std::cout << "Invalid modulo input." << std::endl; return 0; } return mod_exp(base, exp, mod); } //Since function is called recursively, the actual calculation process is done in a separate function, //to avoid redundant base, exp and mod checks. long long mod_exp(long long base, long long exp, long long mod) { if (exp == 1) { return base % mod; } if (exp > 0) { if (exp % 2 == 0) { long long mid = mod_exp(base, exp / 2, mod); return (mid * mid) % mod; } else { return (base * mod_exp(base, exp - 1, mod)) % mod; } } } #endif //Include guard
//Knowledgedump.org - Example file. #include "modular_exp.h" int main() { long long base, pow, mod; base = 123456789; pow = 987654321; mod = 4321; //Print result of 123456789^987654321 mod 4321 to console. std::cout << modular_exp(base, pow, mod) << std::endl; return 0; }
2392