第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

斐波那契:非遞歸與記憶遞歸令人費(fèi)解的時(shí)序結(jié)果

斐波那契:非遞歸與記憶遞歸令人費(fèi)解的時(shí)序結(jié)果

Go
UYOU 2022-09-05 17:55:01
在觀看了麻省理工學(xué)院關(guān)于動(dòng)態(tài)編程的講座后,我想用斐波那契進(jìn)行一些練習(xí)。我首先編寫(xiě)了幼稚的遞歸實(shí)現(xiàn),然后添加了記憶。以下是備忘錄版本:package mainimport (    "fmt")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 main() {    memo := make(map[int]int64)    for i := 0; i < 10000; i++ {        fmt.Printf("fib(%d) = %d\n", i, fib_memoized(i, memo))    }}然后,我繼續(xù)編寫(xiě)該程序的非遞歸版本:package mainimport (    "fmt")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 main() {    for i := 0; i < 10000; i++ {        fmt.Printf("fib(%d) = %d\n", i, fib(i))    }}令我感到困惑的是,記憶化版本似乎至少與非遞歸版本一樣好,有時(shí)甚至優(yōu)于它。當(dāng)然,我期望備忘錄與樸素的遞歸實(shí)現(xiàn)相比帶來(lái)很大的改進(jìn),但我只是無(wú)法弄清楚為什么/如何備忘錄化版本可以與之相提并論,甚至超過(guò)其非遞歸版本。我確實(shí)嘗試過(guò)查看兩個(gè)版本的匯編輸出(通過(guò))獲得,但無(wú)濟(jì)于事。我仍然在備忘錄版本中看到說(shuō)明,在我看來(lái),這應(yīng)該會(huì)產(chǎn)生足夠的開(kāi)銷(xiāo)來(lái)證明它至少略?xún)?yōu)于非遞歸版本。go tool compile -SCALL任何知識(shí)淵博的人可以幫助我了解發(fā)生了什么嗎?附言:我知道整數(shù)溢出;我使用10000只是為了增加負(fù)載。
查看完整描述

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ì)算。memomain

下一點(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


查看完整回答
反對(duì) 回復(fù) 2022-09-05
?
慕哥6287543

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ǔ)句。


查看完整回答
反對(duì) 回復(fù) 2022-09-05
?
慕妹3242003

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


查看完整回答
反對(duì) 回復(fù) 2022-09-05
  • 3 回答
  • 0 關(guān)注
  • 116 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)