Sometimes, casting an Int
to a Double
is not a viable solution. At some magnitudes there is a loss of precision in this conversion. For example, the following code does not return what you might intuitively expect.
Double(Int.max - 1) < Double(Int.max) // false!
If you need precision at high magnitudes and don't need to worry about negative exponents — which can't be generally solved with integers anyway — then this implementation of the tail-recursive exponentiation-by-squaring algorithm is your best bet. According to this SO answer, this is "the standard method for doing modular exponentiation for huge numbers in asymmetric cryptography."
// using Swift 5.0
func pow<T: BinaryInteger>(_ base: T, _ power: T) -> T {
func expBySq(_ y: T, _ x: T, _ n: T) -> T {
precondition(n >= 0)
if n == 0 {
return y
} else if n == 1 {
return y * x
} else if n.isMultiple(of: 2) {
return expBySq(y, x * x, n / 2)
} else { // n is odd
return expBySq(y * x, x * x, (n - 1) / 2)
}
}
return expBySq(1, base, power)
}
Note: in this example I've used a generic T: BinaryInteger
. This is so you can use Int
or UInt
or any other integer-like type.