I am trying to write a function that returns the nth number of the Fibonacci Sequence. I am running into trouble when going from returning an int to a big.Int.
Here is the normal version, which just uses matrix exponentiation to find the nth number of the Fibonacci sequence. It works just fine and returns the value I want:
func normalFib(n int) int {
if n == 0 || n == 1 {
return n
}
n -= 2
a, b, c := 1, 1, 0
x, y := 1, 1
var evenNum [3]int
var oddNum [2]int
for n > 0 {
if n%2 == 0 {
temp := []int{a*a + b*b, a*b + b*c, b*b + c*c}
a, b, c = temp[0], temp[1], temp[2]
copy(evenNum[:], temp)
n /= 2
} else {
temp := []int{x*a + y*b, x*b + y*c}
x, y = temp[0], temp[1]
copy(oddNum[:], temp)
n--
}
}
return oddNum[0]
}
func main() {
fmt.Println(normalFib(10)) // Outputs 55
}
The intermediate values of the above function look like this:
The value of N is currently: 8
The values of a, b, c: 2 1 1
The value of N is currently: 4
The values of a, b, c: 5 3 2
The value of N is currently: 2
The values of a, b, c: 34 21 13
The value of N is currently: 1
The values of x, y: 55 34 // x is correct!
This is the big.Int version. Because of the way the big.Add() and big.Mul() functions work, I've tried working with it by
- creating three result variables d, e, and f that will temporarily store the result of those functions for each value in the temporary array.
- setting the values of a, b, c to the values of the slice (or x, y if it is an odd number)
- copying the temporary slice to its respective array (evenNum or oddNum).
Despite what I've tried, it will still only output multiples of two, which is not what I want:
func bigFib(n int) *big.Int {
if n == 0 || n == 1 {
return big.NewInt(int64(n))
}
n -= 2
a, b, c := big.NewInt(1), big.NewInt(1), big.NewInt(0)
x, y := big.NewInt(1), big.NewInt(0)
var evenNum [3]*big.Int
var oddNum [2]*big.Int
for n > 0 {
if n%2 == 0 {
// Result variables
d, e, f := big.NewInt(0), big.NewInt(0), big.NewInt(0)
// Temporary slice to hold the result of the matrix addition.
temp := []*big.Int{
d.Add(e.Mul(a, a), f.Mul(b, b)),
d.Add(e.Mul(a, b), f.Mul(b, c)),
d.Add(e.Mul(b, b), f.Mul(c, c))}
// Setting a, b, c to the values of the slice.
a, b, c = temp[0], temp[1], temp[2]
// Copying the temp slice to the evenNum array.
copy(evenNum[:], temp)
n /= 2
} else {
// Result variables
d, e, f := big.NewInt(0), big.NewInt(0), big.NewInt(0)
// Temprorary slice to hold the result of the matrix addition.
temp := []*big.Int{
d.Add(e.Mul(x, a), f.Mul(y, b)),
d.Add(e.Mul(x, b), f.Mul(y, c))}
// Set x, y to the values of the slice.
x, y = temp[0], temp[1]
// Copying the temp slice to the oddNum array.
copy(oddNum[:], temp)
n--
}
}
return oddNum[0]
}
func main() {
fmt.Println(bigFib(10)) // Outputs 8
}
The intermediate values for the bigFib function look like this:
The value of N is currently: 8
Value of d, e, f: 1 1 0
Value of a, b, c: 1 1 1
The value of N is currently: 4
Value of d, e, f: 2 1 1
Value of a, b, c: 2 2 2
The value of N is currently: 2
Value of d, e, f: 8 4 4
Value of a, b, c: 8 8 8
The value of N is currently: 1
Value of d, e, f: 8 8 0
Value of x, y: 8 8
If anyone can show me what is going wrong, it would be greatly appreciated.