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"
编译上述程序时出现以下错误。请纠正我
在此声明中,您的问题是双重的:
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)
你看,你索引 by $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"
这仍然可以做 bether 然而,让我们使用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
这是基于您的代码的有效解决方案:
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"