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"
编译上述程序时出现以下错误。请纠正我
答案 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"