TCL:我在创建fibonacci时遇到以下错误

时间:2013-08-07 01:07:57

标签: list tcl

proc Fibonacci {x} {
    set n(0) 0; set n(1) 1
    set i 2
    while {$i <= $x} {
        set n($i) [expr n($i-2) + n($i-1)]
        incr i
    }
    return $n($i)
}
set y [Fibonacci 10]
puts "$y"

编译上述程序时出现以下错误。请纠正我

2 个答案:

答案 0 :(得分:5)

你的问题在本声明中是双重的:

set n($i) [expr n($i-2) + n($i-1)]

首先,您必须获取n($i-2)的值,而不是它的名称,因此您应将其更改为:

set n($i) [expr {$n($i-2) + $n($i-1)}]

我还介绍了{}使expr更整洁,更不容易出错。但是,这仍然不起作用,因为在尝试索引$i-2数组之前不会计算n,所以你需要这个:

set n($i) [expr {$n([expr {$i-2}]) + $n([expr {$i-1}])}]

固定?不,这条线仍然是错误的:

return $n($i)

你看,你按$i编制索引,但是在你的循环中,你写到n($i),然后立即增加i,所以它会比最后一个元素高一个。您需要将其更改为:

return $n($x)

这为您的代码提供了一个工作版本:

proc Fibonacci {x} {
    set n(0) 0
    set n(1) 1
    set i 2
    while {$i <= $x} {
        set n($i) [expr {$n([expr {$i-2}]) + $n([expr {$i-1}])}]
        incr i
    }
    return $n($x)
}
set y [Fibonacci 10]
puts "$y"

然而,这仍然可以使用for代替while:

proc Fibonacci1 {x} {
    set n(0) 0
    set n(1) 1
    for {set i 2} {$i <= $x} {incr i} {
        set n($i) [expr {$n([expr {$i-2}]) + $n([expr {$i-1}])}]
    }
    return $n($x)
}

让我们用列表替换该数组,语义在这里工作得更好:

proc Fibonacci2 {x} {
    set n [list 0 1]
    for {set i 2} {$i <= $x} {incr i} {
        lappend n [expr {[lindex $n end] + [lindex $n end-1]}]
    }
    return [lindex $n end]
}

这里的数组很没用,因为它们实际上是tcl中的关联容器,列表是一个顺序容器,你在这个算法中显然使用了它。你可以在速度上看到这个,这是我在计算机上用tcl 8.6得到的:

time {Fibonacci1 100} 10000
64.1805 microseconds per iteration
time {Fibonacci2 100} 10000
23.9295 microseconds per iteration

答案 1 :(得分:1)

以下是基于您的代码的工作解决方案:

proc Fibonacci {x} {
    set n(0) 0; set n(1) 1
    set i 2 
    while {$i <= $x} {
        set fiboMinus1 $n([expr {$i - 1}])
        set fiboMinus2 $n([expr {$i - 2}])
        set n($i) [expr {$fiboMinus1 + $fiboMinus2}]
        incr i
    }   
    return $n($x)
}   

set y [Fibonacci 10] 
puts "$y"