Fibonacci in Go

51 views
Skip to first unread message

Ricky

unread,
Jun 14, 2012, 4:52:06 AM6/14/12
to Gocn
不太理解这个程序如何通过channel实现累加的

package main

import (
"fmt"
)

func dup3(in <-chan int) (<-chan int, <-chan int, <-chan int) {
a, b, c := make(chan int,2), make(chan int, 2), make(chan int, 2)
go func() {
for {
x := <-in
a <-x
b <-x
c <-x
}
}()
return a, b, c
}

func fib() <-chan int {
x := make(chan int, 2)
a, b, out := dup3(x)
go func() {
x <- 0
x <- 1
<-a
for {
x <- <-a + <-b
}
}()
return out
}

func main() {
x := fib()
for i:=0;i<10;i++ {
fmt.Println(<-x)
}
}

--
_______________
Ricky Ng. Wu
http://richiewu.is-programmer.com/

minux

unread,
Jun 14, 2012, 10:12:46 AM6/14/12
to golang...@googlegroups.com
实际上是两个无限长的序列相加。
注意到,从第三项起,Fibonacci数的后一项是前两项相加得到的。
假设我有一个(无穷)序列x[0:]是连续的Fibonacci数,那么我只要把
x[0:] + x[1:](这里+表示逐项相加)就能得到序列x[2:]。

函数式语言,尤其是Lazy的FP语言,比如Haskell就是可以直接把上述
定义翻译成代码,非常简洁直白:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
(大概解释下,fib就是那个无穷数组x,0:1:是fibs的前两项;后面的项是
fibs[0:]和fibs[1:]逐项相加得到。)

Go里面用channel可以模拟这个无穷序列且不用占用任意多的空间。美
中不足是channel中的东西只能读取一次,所以需要dup3,但是原理就
前面说是那样。

要是觉得这种无限数组的思考方式不熟悉,可以看看Doug McIlroy
Squinting at Power Series论文,Go的官方源代码里有对应的Go实现:

Ricky

unread,
Jun 15, 2012, 3:30:41 AM6/15/12
to golang...@googlegroups.com
我觉得每次能打印channel里的值就更好理解些,但是打印值就得读取一次,矛盾了
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina

minux

unread,
Jun 15, 2012, 4:32:25 AM6/15/12
to golang...@googlegroups.com

2012/6/15 Ricky <ricky...@gmail.com>
我觉得每次能打印channel里的值就更好理解些,但是打印值就得读取一次,矛盾了
可以在读取的地方打印呀。以这个程序为例,其实打印了out出来的值就很明确
地知道是怎么回事儿了。

另外注意在不同goroutine打印多个变量的值的显示顺序可能是不固定的(所谓
concurrent程序的非确定性);比如有多个goroutine都读取同一个channel的时
候;

当然,不影响channel并打印出其中的值也是很方便的,这程序里dup3()函数是
干嘛的?

Ricky

unread,
Jun 15, 2012, 4:43:57 AM6/15/12
to golang...@googlegroups.com
这个累加函数很好理解,就是不理解每一步都是如何从channel里取值的,实时打印值或许就简单得多了
我也不太理解dup3的作用
--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina

minux

unread,
Jun 15, 2012, 5:08:28 AM6/15/12
to golang...@googlegroups.com

2012/6/15 Ricky <ricky...@gmail.com>
这个累加函数很好理解,就是不理解每一步都是如何从channel里取值的,实时打印值或许就简单得多了
什么意思?如何从channel中取值? 
我也不太理解dup3的作用
dup3哪里不理解? 

Ricky

unread,
Jun 15, 2012, 5:26:32 AM6/15/12
to golang...@googlegroups.com
我还是不知道在哪里可以打印值而不影响channel取值,我打印了out没有任何输出

dup3里的这几步,好像是把输入和累加值及输出关联起来:

            x := <-in
            a <-x
            b <-x
            c <-x

--
官网: http://golang-china.org/
IRC: irc.freenode.net #golang-china
@golangchina

minux

unread,
Jun 15, 2012, 5:29:05 AM6/15/12
to golang...@googlegroups.com

2012/6/15 Ricky <ricky...@gmail.com>
我还是不知道在哪里可以打印值而不影响channel取值,我打印了out没有任何输出
用类似dup3()的方式复制一份channel就可以打印值了。 

dup3里的这几步,好像是把输入和累加值及输出关联起来:

            x := <-in
            a <-x
            b <-x
            c <-x
dup3就是复制3份的意思;给一个channel输出3个channel他们都是输入channel的复制品。
Reply all
Reply to author
Forward
0 new messages