3 回答

TA貢獻(xiàn)1155條經(jīng)驗(yàn) 獲得超0個(gè)贊
要記住的一件非常重要的事情是:在測(cè)試平臺(tái)的迭代之間保留。因此,記憶化版本在 中每次迭代循環(huán)時(shí)最多有兩個(gè)遞歸調(diào)用。即,您允許記憶化版本在單個(gè)迭代之間保留內(nèi)存,而迭代版本需要在每次迭代中從頭開(kāi)始計(jì)算。memo
main
下一點(diǎn):
編寫(xiě)基準(zhǔn)測(cè)試很棘手。微小的細(xì)節(jié)可以對(duì)結(jié)果產(chǎn)生重大影響。例如,調(diào)用最有可能需要相當(dāng)長(zhǎng)的時(shí)間來(lái)執(zhí)行,但實(shí)際上并沒(méi)有考慮斐波那契計(jì)算的運(yùn)行時(shí)。我沒(méi)有任何環(huán)境可用于測(cè)試這些 IO 操作實(shí)際影響的時(shí)序程度,但很可能相當(dāng)可觀。特別是因?yàn)槟愕乃惴ㄟ\(yùn)行的迭代次數(shù)相當(dāng)小,只有10000次迭代,或者只有100微秒,正如@Brackens答案中所看到的那樣。printf
總而言之:
從基準(zhǔn)測(cè)試中刪除 IO,在每次迭代中以空開(kāi)頭,并增加迭代次數(shù)以獲得更好的時(shí)機(jī)。memo

TA貢獻(xiàn)1831條經(jīng)驗(yàn) 獲得超10個(gè)贊
我想你是在問(wèn)為什么記憶化的遞歸實(shí)現(xiàn)不比迭代實(shí)現(xiàn)快得多。雖然你提到了一個(gè)你沒(méi)有顯示的“樸素的遞歸實(shí)現(xiàn)”?
使用基準(zhǔn)測(cè)試,您可以看到兩者的性能相當(dāng),也許迭代更快一些:
package kata
import (
"fmt"
"os"
"testing"
)
func fib_memoized(n int, memo map[int]int64) int64 {
memoized, ok := memo[n]
if ok {
return memoized
}
if n < 2 {
return int64(n)
}
f := fib_memoized(n-2, memo) + fib_memoized(n-1, memo)
memo[n] = f
return f
}
func fib(n int) int64 {
var f1 int64 = 1
var f2 int64 = 0
for i := 0; i < n; i++ {
f1, f2 = f2, f1+f2
}
return f2
}
func BenchmarkFib(b *testing.B) {
out, err := os.Create("/dev/null")
if err != nil {
b.Fatal("Can't open: ", err)
}
b.Run("Recursive Memoized", func(b *testing.B) {
memo := make(map[int]int64)
for j := 0; j < b.N; j++ {
for i := 0; i < 100; i++ {
fmt.Fprintf(out, "fib(%d) = %d\n", i, fib_memoized(i, memo))
}
}
})
b.Run("Iterative", func(b *testing.B) {
for j := 0; j < b.N; j++ {
for i := 0; i < 100; i++ {
fmt.Fprintf(out, "fib(%d) = %d\n", i, fib(i))
}
}
})
}
% go test -bench=.
goos: darwin
goarch: amd64
pkg: github.com/brackendawson/kata
cpu: Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
BenchmarkLoop/Recursive_Memoized-12 13424 91082 ns/op
BenchmarkLoop/Iterative-12 13917 82837 ns/op
PASS
ok github.com/brackendawson/kata 4.323s
我希望你的記憶遞歸實(shí)現(xiàn)不會(huì)快得多,因?yàn)椋?/p>
Go 沒(méi)有良好的尾部調(diào)用優(yōu)化 (TCO)。正如您可能已經(jīng)從程序集中看到的那樣,仍然有 CAL,如果 CAL 可以?xún)?yōu)化,則遞歸通常只會(huì)更快。
您的記憶遞歸實(shí)現(xiàn)不是尾部調(diào)用,遞歸調(diào)用必須是函數(shù)中使用 TCO 的最后一個(gè)語(yǔ)句。

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超6個(gè)贊
這不是你的問(wèn)題的答案,但有一種方法可以得到log(N)
中的第N個(gè)斐波那契數(shù)列,你所需要的只是提高矩陣
|0 1 |
|1 1 |
使用二元矩陣冪到 N 的冪
材料鏈接:
https://kukuruku.co/post/the-nth-fibonacci-number-in-olog-n/
https://www.youtube.com/watch?v=eMXNWcbw75E
- 3 回答
- 0 關(guān)注
- 116 瀏覽
添加回答
舉報(bào)