├── fib ├── example_test.go ├── fib_test.go └── fib.go ├── README.md ├── main.go └── LICENSE /fib/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 visualfc . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package fib 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | func ExampleFibList() { 12 | fmt.Println(FibList(-10, 10)) 13 | // Output: [-55 34 -21 13 -8 5 -3 2 -1 1 0 1 1 2 3 5 8 13 21 34 55] 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | fibutil 2 | ======= 3 | 4 | Golang Fibonacci numbers library 5 | 6 | Fibonacci numbers integer sequence: 7 | 8 | 0 1 1 2 3 5 8 13 21 34 55 89 144 ... 9 | -21 13 -8 5 -3 2 -1 1 0 1 1 2 3 5 8 13 21 ... 10 | 11 | ### Install 12 | 13 | go get -v github.com/visualfc/fibutil 14 | 15 | ### fibutil/fib 16 | 17 | func fib.Fib(n int64) *big.Int 18 | func fib.FastFib(n int64) *big.Int 19 | func fib.FibList(n1, n2 int64) []string 20 | 21 | ### fibutil 22 | Fibonacci number util 23 | 24 | **Usage:** 25 | 26 | fibutil n :fibonacci number 27 | fibutil n1 n2 :fibonacci number list 28 | 29 | **Example:** 30 | 31 | fibutil 10 => 55 32 | fibutil -10 10 => [-55 34 -21 13 -8 5 -3 2 -1 1 0 1 1 2 3 5 8 13 21 34 55] 33 | fibutil 299 => 137347080577163115432025771710279131845700275212767467264610201 34 | 35 | ### License: 36 | 37 | BSD License -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 visualfc . All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // fibutil project main.go 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | "github.com/visualfc/fibutil/fib" 11 | "os" 12 | "strconv" 13 | ) 14 | 15 | func main() { 16 | switch len(os.Args) { 17 | case 2: 18 | n, err := strconv.ParseInt(os.Args[1], 10, 64) 19 | if err == nil { 20 | fmt.Println(fib.FastFib(n)) 21 | return 22 | } 23 | 24 | case 3: 25 | n1, e1 := strconv.ParseInt(os.Args[1], 10, 64) 26 | n2, e2 := strconv.ParseInt(os.Args[2], 10, 64) 27 | if e1 == nil && e2 == nil { 28 | fmt.Println(fib.FibList(n1, n2)) 29 | return 30 | } 31 | } 32 | fmt.Fprintf(os.Stderr, "%s, Fibonacci number util\n\tfibutil n\t: Fibonacci number\n\tfibutil n1 n2\t: Fibonacci number list\n", os.Args[0]) 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 visualfc . All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /fib/fib_test.go: -------------------------------------------------------------------------------- 1 | package fib 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestFibm(t *testing.T) { 8 | ar := []int64{0, 1, 1, 2, 3, 5, 8, 13, 21} 9 | for i := 0; i < len(ar); i++ { 10 | if ar[i] != Fibm(int64(i)) { 11 | t.Fatalf("%d, %d != %d", i, ar[i], Fibm(int64(i))) 12 | } 13 | } 14 | ar1 := []int64{0, 1, -1, 2, -3, 5, -8, 13, -21} 15 | for i := 0; i < len(ar1); i++ { 16 | if ar1[i] != Fibm(int64(-i)) { 17 | t.Fatalf("%d, %d != %d", -i, ar1[i], Fibm(int64(-i))) 18 | } 19 | } 20 | } 21 | 22 | func TestFibm2(t *testing.T) { 23 | ar := []int64{0, 1, 1, 2, 3, 5, 8, 13, 21} 24 | for i := 0; i < len(ar); i++ { 25 | if ar[i] != Fibm2(int64(i)) { 26 | t.Fatalf("%d, %d != %d", i, ar[i], Fibm2(int64(i))) 27 | } 28 | } 29 | ar1 := []int64{0, 1, -1, 2, -3, 5, -8, 13, -21} 30 | for i := 0; i < len(ar1); i++ { 31 | if ar1[i] != Fibm2(int64(-i)) { 32 | t.Fatalf("%d, %d != %d", -i, ar1[i], Fibm2(int64(-i))) 33 | } 34 | } 35 | } 36 | 37 | func TestFib(t *testing.T) { 38 | ar := []int64{0, 1, 1, 2, 3, 5, 8, 13, 21} 39 | for i := 0; i < len(ar); i++ { 40 | if ar[i] != Fib(int64(i)).Int64() { 41 | t.Fatalf("%d, %d != %d", i, ar[i], Fib(int64(i)).Int64()) 42 | } 43 | } 44 | ar1 := []int64{0, 1, -1, 2, -3, 5, -8, 13, -21} 45 | for i := 0; i < len(ar1); i++ { 46 | if ar1[i] != Fib(int64(-i)).Int64() { 47 | t.Fatalf("%d, %d != %d", -i, ar1[i], Fib(int64(-i))) 48 | } 49 | } 50 | } 51 | 52 | func TestFastFib(t *testing.T) { 53 | ar := []int64{0, 1, 1, 2, 3, 5, 8, 13, 21} 54 | for i := 0; i < len(ar); i++ { 55 | if ar[i] != FastFib(int64(i)).Int64() { 56 | t.Fatalf("%d, %d != %d", i, ar[i], FastFib(int64(i))) 57 | } 58 | } 59 | ar1 := []int64{0, 1, -1, 2, -3, 5, -8, 13, -21} 60 | for i := 0; i < len(ar1); i++ { 61 | if ar1[i] != FastFib(int64(-i)).Int64() { 62 | t.Fatalf("%d, %d != %d", -i, ar1[i], FastFib(int64(-i))) 63 | } 64 | } 65 | } 66 | 67 | func BenchmarkFibm(b *testing.B) { 68 | for i := 0; i < b.N; i++ { 69 | Fibm(90) 70 | } 71 | } 72 | 73 | func BenchmarkFibm2(b *testing.B) { 74 | for i := 0; i < b.N; i++ { 75 | Fibm2(90) 76 | } 77 | } 78 | 79 | func BenchmarkFib(b *testing.B) { 80 | for i := 0; i < b.N; i++ { 81 | Fib(90) 82 | } 83 | } 84 | 85 | func BenchmarkFastFib(b *testing.B) { 86 | for i := 0; i < b.N; i++ { 87 | FastFib(90) 88 | } 89 | } 90 | 91 | func BenchmarkFib200(b *testing.B) { 92 | for i := 0; i < b.N; i++ { 93 | Fib(200) 94 | } 95 | } 96 | 97 | func BenchmarkFastFib200(b *testing.B) { 98 | for i := 0; i < b.N; i++ { 99 | FastFib(200) 100 | } 101 | } 102 | 103 | func BenchmarkFib1000(b *testing.B) { 104 | for i := 0; i < b.N; i++ { 105 | Fib(1000) 106 | } 107 | } 108 | 109 | func BenchmarkFastFib1000(b *testing.B) { 110 | for i := 0; i < b.N; i++ { 111 | FastFib(1000) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /fib/fib.go: -------------------------------------------------------------------------------- 1 | // fibonacci number 2 | // 3 | // 0 1 1 2 3 5 8 13 21 34 55 89 144 ... 4 | // 5 | // -21 13 -8 5 3 2 1 1 0 1 1 2 3 5 8 13 21 ... 6 | package fib 7 | 8 | import ( 9 | "fmt" 10 | "math/big" 11 | ) 12 | 13 | // 非递归方式实现Fibonacci算法 14 | func Fibm(n int64) int64 { 15 | if n == 0 { 16 | return 0 17 | } 18 | var i, a, b int64 19 | b = 1 20 | if n < 0 { 21 | n = -n 22 | if n%2 == 0 { 23 | b = -1 24 | } 25 | } 26 | for i = 2; i <= n; i++ { 27 | a, b = b, a+b 28 | } 29 | return b 30 | } 31 | 32 | // 递归方式实现Fibonacci算法 33 | func Fibm2(n int64) int64 { 34 | if n < 0 { 35 | if n%2 == 0 { 36 | return _Fibm2(-n, 0, -1) 37 | } else { 38 | return _Fibm2(-n, 0, 1) 39 | } 40 | } 41 | return _Fibm2(n, 0, 1) 42 | } 43 | 44 | func _Fibm2(n, a1, a2 int64) int64 { 45 | if n == 0 { 46 | return a1 47 | } 48 | return _Fibm2(n-1, a2, a1+a2) 49 | } 50 | 51 | // big.Int实现Fibonacci算法 52 | func Fib(n int64) *big.Int { 53 | if n == 0 { 54 | return big.NewInt(0) 55 | } 56 | a, b, c := big.NewInt(0), big.NewInt(1), big.NewInt(0) 57 | if n < 0 { 58 | n = -n 59 | if n%2 == 0 { 60 | b.SetInt64(-1) 61 | } 62 | } 63 | for i := int64(2); i <= n; i++ { 64 | c.Set(a) 65 | a.Set(b) 66 | b.Add(b, c) 67 | } 68 | return b 69 | } 70 | 71 | type Matrix struct { 72 | M00, M01, M10, M11 *big.Int 73 | } 74 | 75 | func NewMatrix(M00, M01, M10, M11 int64) *Matrix { 76 | return &Matrix{big.NewInt(M00), big.NewInt(M01), big.NewInt(M10), big.NewInt(M11)} 77 | } 78 | 79 | func (m *Matrix) String() string { 80 | return fmt.Sprintf("[%s,%s;%s;%s]", m.M00, m.M01, m.M10, m.M11) 81 | } 82 | 83 | func (m *Matrix) Mul(other *Matrix) *Matrix { 84 | var a, a1, b, b1, c, c1, d, d1 big.Int 85 | return &Matrix{ 86 | a.Mul(m.M00, other.M00).Add(&a, a1.Mul(m.M01, other.M10)), 87 | b.Mul(m.M00, other.M01).Add(&b, b1.Mul(m.M01, other.M11)), 88 | c.Mul(m.M10, other.M00).Add(&c, c1.Mul(m.M11, other.M10)), 89 | d.Mul(m.M10, other.M01).Add(&d, d1.Mul(m.M11, other.M11))} 90 | } 91 | 92 | func (m *Matrix) Pow(n int64) *Matrix { 93 | if n == 1 { 94 | return m 95 | } else if n%2 == 0 { 96 | out := m.Pow(n / 2) 97 | return out.Mul(out) 98 | } else { 99 | out := m.Pow((n - 1) / 2) 100 | out = out.Mul(out) 101 | return out.Mul(m) 102 | } 103 | return nil 104 | } 105 | 106 | // 使用矩阵求解Fibonacci算法 107 | func FastFib(n int64) *big.Int { 108 | if n == 0 { 109 | return big.NewInt(0) 110 | } else if n == 1 || n == -1 { 111 | return big.NewInt(1) 112 | } 113 | m := NewMatrix(1, 1, 1, 0) 114 | if n < 0 { 115 | n = -n 116 | if n%2 == 0 { 117 | m.M00.SetInt64(-1) 118 | } 119 | } 120 | return m.Pow(n - 1).M00 121 | } 122 | 123 | // big.Int实现Fibonacci列表 124 | func FibList(n1, n2 int64) []string { 125 | size := n2 - n1 126 | if size < 0 { 127 | return nil 128 | } else if size == 0 { 129 | return []string{FastFib(n1).String()} 130 | } 131 | a := FastFib(n1) 132 | b := FastFib(n1 + 1) 133 | r := make([]string, size+1) 134 | r[0] = a.String() 135 | r[1] = b.String() 136 | var tmp big.Int 137 | for i := int64(2); i <= size; i++ { 138 | tmp.Set(a) 139 | a.Set(b) 140 | b.Add(b, &tmp) 141 | r[i] = b.String() 142 | } 143 | return r 144 | } 145 | --------------------------------------------------------------------------------