如何在Golang中将int转换为bigint?

16

我正在尝试实现快速双倍斐波那契算法,如此处所述

// Fast doubling Fibonacci algorithm
package main

import "fmt"

//  (Public) Returns F(n).
func fibonacci(n int) int {
    if n < 0 {
        panic("Negative arguments not implemented")
    }
    fst, _ := fib(n)
    return fst
}

// (Private) Returns the tuple (F(n), F(n+1)).
func fib(n int) (int, int) {
    if n == 0 {
        return 0, 1
    }
    a, b := fib(n / 2)
    c := a * (b*2 - a)
    d := a*a + b*b
    if n%2 == 0 {
        return c, d
    } else {
        return d, c + d
    }
}

func main() {
    fmt.Println(fibonacci(13))
    fmt.Println(fibonacci(14))
}

这个方法对于小数字效果很好;但是,当输入的数字越来越大时,程序返回错误的结果。因此,我尝试使用math/big包中的bigInt

// Fast doubling Fibonacci algorithm
package main

import (
    "fmt"
    "math/big"
)

//  (Public) Returns F(n).
func fibonacci(n int) big.Int {
    if n < 0 {
        panic("Negative arguments not implemented")
    }
    fst, _ := fib(n)
    return fst
}

// (Private) Returns the tuple (F(n), F(n+1)).
func fib(n int) (big.Int, big.Int) {
    if n == 0 {
        return big.Int(0), big.Int(1)
    }
    a, b := fib(n / 2)
    c := a * (b*2 - a)
    d := a*a + b*b
    if n%2 == 0 {
        return c, d
    } else {
        return d, c + d
    }
}

func main() {
    fmt.Println(fibonacci(123))
    fmt.Println(fibonacci(124))
}

然而,go build报错了:

cannot convert 0 (type int) to type big.Int

如何缓解这个问题?


尝试使用big.Int64(int-number) - aggaton
1个回答

17
请使用big.NewInt()而不是big.Int()big.Int()只是类型转换。 您需要查看大数包文档
您应该大多数使用形式为func (z *T) Binary(x, y *T) *T // z = x op y的方法
要乘以2个参数,您需要提供结果变量,然后调用Mul方法。 因此,例如,要获得2 * 2的结果,您需要:
big.NewInt(0).Mul(big.NewInt(2), big.NewInt(2))

您可以在Go playground上尝试工作示例

您还可以创建扩展函数,例如:

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

为了使代码更易读:
// Fast doubling Fibonacci algorithm
package main

import (
    "fmt"
    "math/big"
)

//  (Public) Returns F(n).
func fibonacci(n int) *big.Int {
    if n < 0 {
        panic("Negative arguments not implemented")
    }
    fst, _ := fib(n)
    return fst
}

// (Private) Returns the tuple (F(n), F(n+1)).
func fib(n int) (*big.Int, *big.Int) {
    if n == 0 {
        return big.NewInt(0), big.NewInt(1)
    }
    a, b := fib(n / 2)
    c := Mul(a, Sub(Mul(b, big.NewInt(2)), a))
    d := Add(Mul(a, a), Mul(b, b))
    if n%2 == 0 {
        return c, d
    } else {
        return d, Add(c, d)
    }
}

func main() {
    fmt.Println(fibonacci(123))
    fmt.Println(fibonacci(124))
}

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

请在Go playground上试用一下


我得到了无法将big.NewInt(0)(类型为*big.Int)用作返回参数的big.Int类型 - Nick
你的扩展函数想法真是太棒了!它让代码变得更加简洁!非常感谢!附言:c := Mul(a, Sub(Mul(b, big.NewInt(2)), a)) 看起来像 LISP :) - Nick
@Nick,如果一个人关心分配和性能,那么“扩展函数的想法”并不是那么出色。在Go1.0之前,math/big库的操作方式类似,但为了编写更(多)高效的代码,它被改成了当前的形式,以避免过度测试垃圾回收器。 - Dave C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接