Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert int to bigint in golang?

Tags:

go

I'm trying to implement fast double Fibonacci algorithm as described here:

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

This works fine for small numbers; however, when the input number get larger, the program returns a wrong result. So I tried to use bigInt from math/big package:

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

However, go build complains that

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

How to mitigate this problem?

like image 805
Nick Avatar asked Nov 12 '15 03:11

Nick


People also ask

What is big int Golang?

Golang doesn't check for overflows implicitly and so this may lead to unexpected results when a number larger than 64 bits are stored in a int64. To solve this problem, Go provides the Package “big” which implements arbitrary-precision arithmetic (big numbers).

How do you change type in Golang?

Go is a statically typed language, which means types of variables must be known at compile time, and you can't change their type at runtime.


1 Answers

Use big.NewInt() instead of big.Int(). big.Int() is just type casting. You need to check out documentation of big package
You should mostly use methods with form func (z *T) Binary(x, y *T) *T // z = x op y
To multiply 2 arguments you need to provide result variable, after it call Mul method. So, for example, to get result of 2*2 you need to:
big.NewInt(0).Mul(big.NewInt(2), big.NewInt(2))

You can try working example on the Go playground

Also you can create extension functions like:

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

To make code more readable:

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

Try it on the Go playground

like image 118
RoninDev Avatar answered Sep 18 '22 06:09

RoninDev