在 Golang 中计算大幂

Calculating large exponentiation in Golang

我一直在尝试用 Golang 计算 2^100。我了解 limit of numeric type 并尝试使用 math/big 包。这是我尝试过的方法,但我不明白为什么它不起作用。

我使用了computation by powers of two 方法来计算幂。

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)
}

如果 power % 2 == 0,您将立即返回。相反,您只想获得 base ** (power /2)result。然后乘以 result * result,如果 power 是偶数,则乘以 base

例如,

package main

import (
    "fmt"
    "math/big"
)

func main() {
    z := new(big.Int).Exp(big.NewInt(2), big.NewInt(100), nil)
    fmt.Println(z)
}

输出:

1267650600228229401496703205376

因为它是 2 的幂,你也可以做一点移位:

package main

import (
    "fmt"
    "math/big"
)

func main() {
    z := new(big.Int).Lsh(big.NewInt(1), 100)
    fmt.Println(z)
}

输出:

1267650600228229401496703205376

BigInt 包允许您calculate x^y in log time(由于某种原因它被称为 exp)。您只需要将 nil 作为最后一个参数传递即可。

package main

import (
    "fmt"
    "math/big"
)

func main() {
    fmt.Println(new(big.Int).Exp(big.NewInt(5), big.NewInt(20), nil))
}

有兴趣自己计算的可以看看我的实现:

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
}

或在 go playground.

上玩

计算2^100

package main

import (
    "fmt"
    "math/big"
)

func main() {
    n := big.NewInt(0)
    fmt.Println(n.SetBit(n, 100, 1))
}

Playground

package main

import(
    "fmt"
    "math/big"
)

func main() {

    bigx, power10 := new(big.Int), new(big.Int)
    var x int64
    bigx.SetInt64(x) //set x int64 to bigx
    power10.Exp(big.NewInt(10), bigx, nil) //power10 *big.Int points to solution

    str10 := power10.Text(10)
    fmt.Printf(str10) // print out the number and check for your self

}