-2
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"

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

4

2 回答 2

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)

你看,你索引 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
于 2013-08-07T08:16:18.607 回答
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"
于 2013-08-07T01:34:48.243 回答