Reputation: 10801
How to calculate a**b % m
where all the members are integers, and a^b
is outside the int
range?
I.e. to raise a
to the power b
under modulo m
. I.e. an equivalent of this Python code:
pow(a, b, m)
Upvotes: 2
Views: 386
Reputation: 10801
Calculating the exponent manually as suggested by Robby, but efficiently:
func pow(a, b, m int) int {
if b < 0 {
panic("Negative power given")
}
result := 1
power := a
for b > 0 {
if b & 1 == 1 {
result = result * power % m
}
power = power * power % m
b >>= 1
}
return result
}
This is an iterative version of exponentiation by squaring. The time complexity is O(log(b)) if we assume that every multiplication takes O(1) time.
If m
is prime, it's possible to calculate the negative power. It requires 2 steps:
func powUniversal(a, b, m int) int {
if b >= 0 {
return pow(a, b, m)
}
subResult := pow(a, -b, m)
return pow(subResult, m - 2, m)
}
You can check that it works by asserting powUniversal(a, b, m) * powUniversal(a, -b, m) % m == 1
.
Upvotes: 0
Reputation: 97120
It should be possible to do this in a more memory-efficient way, without resorting to big integers.
This is a direct translation from the pseudocode found on Wikipedia:
package main
import (
"fmt"
)
func modPow(a, b, m int) int {
if m == 1 {
return 0
}
c := 1
for i := 0; i < b; i++ {
c = (c * a) % m
}
return c
}
func main() {
fmt.Println(modPow(1234, 5678, 9012))
}
Disclaimer: I don't know golang :)
Upvotes: 0
Reputation: 10801
Use the Exp function from the built-in math/big package. But it requires plenty of type conversions.
import "math/big"
func pow(a, b, m int) int {
result := new(big.Int).Exp(
big.NewInt(int64(a)),
big.NewInt(int64(b)),
big.NewInt(int64(m)),
)
return int(result.Uint64())
}
Upvotes: 1