Search code examples
goexponentiation

Calculating large exponentiation in Golang


I've been trying to calculating 2^100 in Golang. I understand the limit of numeric type and tried using math/big package. Here's what I've tried but I can't figure out why it doesn't work.

I've used computation by powers of two method to calculate the exponentiation.

package main

import (
    "fmt"
    "math/big"
)

func main() {
    two := big.NewInt(2)
    hundred := big.NewInt(50)
    fmt.Printf("2 ** 100    is %d\n", ExpByPowOfTwo(two, hundred))
}

func ExpByPowOfTwo(base, power *big.Int) *big.Int {
    result := big.NewInt(1)
    zero := big.NewInt(0)
    for power != zero {
        if modBy2(power) != zero {
            multiply(result, base)
        }
        power = divideBy2(power)
        base = multiply(base, base)
    }
    return result
}

func modBy2(x *big.Int) *big.Int {
    return big.NewInt(0).Mod(x, big.NewInt(2))
}

func divideBy2(x *big.Int) *big.Int {
    return big.NewInt(0).Div(x, big.NewInt(2))
}

func multiply(x, y *big.Int) *big.Int {
    return big.NewInt(0).Mul(x, y)
}

Solution

  • BigInt package allows you to calculate x^y in log time (for some reason it is called exp). All you need is to pass nil as a last parameter.

    package main
    
    import (
        "fmt"
        "math/big"
    )
    
    func main() {
        fmt.Println(new(big.Int).Exp(big.NewInt(5), big.NewInt(20), nil))
    }
    

    If you are interested how to calculate it by yourself, take a look at my implementation:

    func powBig(a, n int) *big.Int{
        tmp := big.NewInt(int64(a))
        res := big.NewInt(1)
        for n > 0 {
            temp := new(big.Int)
            if n % 2 == 1 {
                temp.Mul(res, tmp)
                res = temp
            }
            temp = new(big.Int)
            temp.Mul(tmp, tmp)
            tmp = temp
            n /= 2
        }
        return res
    }
    

    or play with it on go playground.