亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

計算預定義數字類型之外的大量數字

計算預定義數字類型之外的大量數字

Go
泛舟湖上清波郎朗 2022-06-21 16:45:32
作為家庭作業的一部分,我正在研究斐波那契數發生器。用預定義的數字類型(例如 Go 中的 int32)表示這些斐波那契數的輸出變得不可能,您必須使用類似這樣的東西來處理大量數字: https ://golang.org/pkg/math/big/如果我們稍微改變問題的詢問,而不是詢問第 1,000 個斐波那契數的結果,而是詢問相同數字的最后一位,Go 可以毫無問題地處理這個問題。我的問題是:Go 是否能夠計算非常大的數字,因為當數字開始變得非常大時需要更多內存時,語言能夠擴展堆棧大?。慨斶@些數字開始變得如此之大以至于無法放入內存中的 32 或 64 位整數類型時,它們在哪里/如何存儲它們?如果 Go 能夠對不適合 int32 等基本類型的大量數字進行計算,為什么該語言會強制您將這些數字存儲在一個太小而無法處理的基本類型中?例如,如果 Go 能夠將兩個非常大的數字相加并確定一個看似沒有問題的結果,為什么我不能存儲這個值以供將來使用或不使用另一個庫將其打印到屏幕上呢?我想我不確定為什么如果在幕后 Go 能夠很好地對它們進行操作,那么在嘗試執行諸如將它們打印到屏幕之類的操作時,為什么數字必須適合預定義的大小。這是一些示例代碼,我在其中存儲并打印第 n 個斐波那契數的最后一位,而不是打印出第 n 個項的實際值,因為數字變得如此之大。請注意,我仍然如何在 append 語句中添加這些大量數字,但只存儲最后一個數字。似乎 Go 使用“ascii”排序。您可以collate "C"在 Postgres 中使用:SELECT wordfrom unnest(ARRAY['Go', '[Bravo]', 'Gopher', '[Alpha]', 'Grin', 'Delta']) as t(word) ORDER BY word collate "C" ;package mainimport "fmt"func main() {    var n int    var fibNums = []int{0, 1}    var i int    fmt.Scanln(&n)    for i = 0; i < n; i++ {        fibNums = append(fibNums, (fibNums[i]+fibNums[i+1])%10)    }    fmt.Println(fibNums[len(fibNums)-2])}
查看完整描述

2 回答

?
阿晨1998

TA貢獻2037條經驗 獲得超6個贊

Go 是否能夠計算非常大的數字,因為當數字開始變得非常大時需要更多內存時,語言能夠擴展堆棧大小?當這些數字開始變得如此之大以至于無法放入內存中的 32 或 64 位整數類型時,它們在哪里/如何存儲它們?


有點 - 它能夠做到這一點,因為當您使用 時math.Big,它本質上是將每個數字存儲為 的切片uint,以及一些額外的字段(例如數字的符號),其中切片中的每個項目代表單個數字數字。


如果 Go 能夠對不適合 int32 等基本類型的大量數字進行計算,為什么該語言會強制您將這些數字存儲在一個太小而無法處理的基本類型中?


該語言不會強迫您將它們存儲在該類型中 - 您可以自由使用math.Big所有數字。但一般來說,我們希望我們的代碼能夠快速運行,并且需要做的工作量是:


x := 21

y := 29

z := x + y

很少,而且會跑的很快。但這是一種折衷——你只需要意識到像這樣簡單的事情,當將每個數字存儲在一個切片中時,會變成更多的步驟。作為一個快速演示:(https://play.golang.org/p/rFWKbKy4FeQ):


x := []uint{2,1}

y := []uint{2,9}

result := []uint{}

xIndex := len(x) - 1

yIndex := len(y) - 1

carry := 0

for ; xIndex >= 0 || yIndex >= 0; {

    z := uint(0)

    if xIndex >= 0 && yIndex >= 0 {

        z = x[xIndex] + y[yIndex]

    } else if xIndex >= 0 {

        z = x[xIndex]

    } else {

        z = y[yIndex]

    }

    if carry != 0 {

        z++

    }

    if z >= 10 {

        carry = 1

        z = z % 10

    }

    xIndex--

    yIndex--

    result = append([]uint{z}, result...)

}

fmt.Println(result)

我仍然會得到正確的答案(在這種情況下,我什至還沒有擔心任何邊緣情況),但還有很多工作要做。如果每個數學運算都需要這么多的工作,那么 Go 就不會被認為是一種快速語言。


查看完整回答
反對 回復 2022-06-21
?
躍然一笑

TA貢獻1826條經驗 獲得超6個贊

Go 是否能夠計算非常大的數字,因為當數字開始變得非常大時需要更多內存時,語言能夠擴展堆棧大???

不,堆棧和數學/大是完全無關的。

當這些數字開始變得如此之大以至于無法放入內存中的 32 或 64 位整數類型時,它們在哪里/如何存儲它們?

“哪里”:沒人知道。去吧,該語言不對事物的“存儲位置”做出任何聲明/保證。普通計算機有一個堆棧和一個堆,兩個最常見的 Go 編譯器決定將 math/big.Int 放在哪里。這個決定是針對每個變量單獨做出的。請注意,不同的編譯器版本可能會做出不同的決定。(谷歌“逃逸分析”了解詳情)。您可以假設 math/big.Int 存儲在堆中。

“如何”:閱讀 math/big.Int 的來源 :-) 基本上是幾個原始整數。請參閱https://golang.org/src/math/big/nat.go#L23(大致就像您以十進制編碼 > 9 的數字)。

如果 Go 能夠對不適合 int32 等基本類型的大量數字進行計算,為什么該語言會強制您將這些數字存儲在一個太小而無法處理的基本類型中?

這個問題假設“語言迫使您將這些數字存儲在一個太小而無法處理它們的基本類型中”,這是錯誤的。Go 中的“最大”整數類型是 uint64,如果這還不夠,您可以使用 math/big.Int 并且沒有人強迫您將 math/big.Int 存儲在其中一種原始類型中。

例如,如果 Go 能夠將兩個非常大的數字相加并確定一個看似沒有問題的結果,為什么我不能存儲這個值以供將來使用或不使用另一個庫將其打印到屏幕上呢?

假設“Go”是指原始內置類型:不,此 Go 無法對不適合使用的原始類型的數字進行計算。要對“大量數字”進行正確計算,您必須使用包 math/big。

請注意,一旦一個數字溢出 int(通常為 9223372036854775807),您的“斐波那契數的最后一位是完全錯誤的。Go over-/underflow 中的原始類型(在規范中查找確切的詳細信息)在這種情況下,結果定義明確但沒有比你期望的更長。

(旁注:Go 對常量的處理是不同的。)


查看完整回答
反對 回復 2022-06-21
  • 2 回答
  • 0 關注
  • 157 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號