成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Go標準庫的新 math/rand,你看明白了嗎?

開發 前端
Rust中的Rng?類似這里的Go的Source?,可以有多種實現生成器。Rust中的Rand?也類似這里Go的Rand?,基于Uint64() uint64提供各種類型的隨機數。

Go 1.22 就要在龍年春節期間發布了。Go 1.22的新特性包括了新的 math/rand 包。這個包的目標是提供一個更好的偽隨機數生成器,它的 API 也更加簡單易用。本文將介紹這個新的包的特性。

Go 1.22 release notes[1] 正在編寫之中,大家可以關注這個網頁以便全面了解Go 1.22的變化,前幾天有Gopher制作了一個交互式運行新特性代碼的網頁[2],也非常好,在reddit上關注度很高。今天這篇文章只關注于于math/rand/v2這個新的包。

為什么要新的math/rand包

其實大家對math/rand不是那么滿意。

2017年,#20661[3] 中提到math/rand.Read和crypto/rand.Read相近,導致本來應該使crypto/rand.Read的地方使用了math/rand.Read,導致了安全問題。

2017年,#21835[4] 中 Rob Pike 提議在Go 2中使用PCG Source。

2018年,#26263[5] 中 Josh Bleecher Snyder 提議對math/rand進行徹底的重構。

2023年6月, Russ Cox基于先前的對math/rand的吐槽,以及和Rob Pike的討論,建立了一個討論(#60751[6]),準備新建一個包math/rand/v2,重新設計和實現一個新的偽隨機數的庫討論也很熱烈,最后實現了一個提案#61716[7],這個提案最直接的動機是清理 math/rand 并解決其中許多懸而未決的問題,特別是使用過時生成器、緩慢的算法,以及與 crypto/rand.Read 的不幸沖突。

由于go module的支持版本v2、v3、..., Go 1.22中將會有一個新的包math/rand/v2,這個包將會是一個新的包,而不是math/rand的升級版本。這個包的目標是提供一個更好的偽隨機數生成器,它的 API 也更加簡單易用,同時一些檢查工具也能支持這個包,不會報錯。

看樣子,math/rand/v2將會是第一個在標準庫中建立v2版本的包,如果大家能夠接受,將來會有更多的包加入進來,比如sync/v2、encoding/json/v2等等。

提案的主要內容

math/rand/v2 API 以 math/rand 為起點,進行以下不兼容的更改:

1、 移除 Rand.Read 和頂層的 Read。假裝偽隨機生成器是任意長字節序列的良好來源幾乎總是錯誤的。math/rand 適用于模擬和非確定性算法,幾乎從不需要字節序列。Read 是 math/rand 和 crypto/rand 之間唯一共享的 API 部分,代碼應該基本上總是使用 crypto/rand.Read。(math/rand.Read 和 crypto/rand.Read 存在問題,因為它們具有相同的簽名; math/rand.Int 和 crypto/rand.Int 也都存在,但具有不同的簽名,這意味著代碼永遠不會意外地將一個錯認為是另一個。)

2、 移除 Source.Seed、Rand.Seed 和頂層的 Seed。頂層的 Seed 已在 Go 1.20 中廢棄。Source.Seed 和 Rand.Seed 假定底層源可以由單個 int64 作為種子,這只對有限數量的源是真實的。具體的源實現可以提供具有適當簽名的 Seed 方法,或者對于不能重新設置種子的生成器根本不提供;簡單來說使用一個int64 作為種子沒有普適性,不適合定義一個通用的接口。

注意,移除頂層 Seed 意味著頂層函數如 Int 將始終以隨機方式而不是確定性方式生成。math/rand/v2 將不關注 math/rand 所關注的 [randautoseed](https://tip.golang.org/doc/go1.20#mathrandpkgmathrand "randautoseed") GODEBUG 設置;頂層函數的自動設置哦隨機種子是唯一的模式。這反過來意味著頂層函數使用的具體 PRNG 算法是未指定的,可以在發布之間更改而不破壞任何現有代碼。

3、 將 Source 接口更改為具有單個 Uint64() uint64 方法,取代 Int63() int64。后者過于擬合原始的 Mitchell & Reeds LFSR 生成器。現代生成器可以提供 uint64。

4、 移除 Source64,現在不再需要,因為 Source 提供了 Uint64 方法。

5、 在 Float32 和 Float64 中使用更直觀的實現。以 Float64 為例,它最初使用 float64(r.Int63()) / (1<<63),但這存在問題,偶爾會四舍五入為 1.0。我們嘗試將其更改為 float64(r.Int63n(1<<53) / (1<<53),避免了四舍五入的問題。

6、 修復 ExpFloat64 和 NormFloat64 中的偏差問題。

7、 使用 Rand.Shuffle 實現 Rand.Perm。

8、 將 Intn、Int31、Int31n、Int63、Int64n 重命名為 IntN、Int32、Int32N、Int64、Int64N。原來的名稱中的 31 和 63 是令人困惑的,而大寫 N 在 Go 中作為名稱的第二個“單詞”更為習慣。

9、 添加 Uint32、Uint32N、Uint64、Uint64N、Uint、UintN,既作為頂層函數,也作為 Rand 的方法。

10、在 N、IntN、UintN 等中使用 Lemire[8] 的算法。初步基準測試顯示,與 v1 Int31n 相比,節省了 40%,與 v1 Int63n 相比,節省了 75%。

11、添加一個通用的頂層函數 N,類似于 Int64N 或 Uint64N,但適用于任何整數類型。特別是這允許使用 rand.N(1*time.Minute) 來獲取范圍在 [0, 1*time.Minute) 內的隨機持續時間。

12、添加一個新的 Source 實現,PCG-DXSM。PCG 是一個簡單、高效的算法,具有良好的統計隨機性質。DXSM 變體是作者專門為糾正原始 (PCG-XSLRR) 中的一種罕見、隱晦的缺陷而引入的,并且現在是 Numpy 中的默認生成器。

13、移除 Mitchell & Reeds LFSR 生成器和 NewSource。

14、添加一個新的 Source 實現,ChaCha8。ChaCha8 是從 ChaCha8 流密碼派生的具有強密碼學隨機性質的隨機數生成器。它提供與 ChaCha8 加密等效的安全性。

15、在 math/rand/v2 和 math/rand(未設置種子時)中使用每個 OS 線程的 ChaCha8 作為全局隨機生成器。

math/rand/v2介紹

注意,根據go module的定義,v2只是版本號,新的包名還是叫做rand。

rand 包實現了適用于模擬(simulation)等任務的偽隨機數生成器,但不應用于對安全性敏感的工作。

隨機數由 Source生成,通常包裝在 Rand 中。這兩種類型應該一次由單個 goroutine 使用:在多個 goroutine 之間共享需要某種形式的同步。

頂層函數,如 Float64 和 Int,對于多個 goroutine 的并發使用是安全的。

該包的輸出可能在設置種子的方式不同的情況下很容易可預測。對于適用于對安全性敏感的工作的隨機數,請參閱 crypto/rand 包。

簡單綜述:所以你考慮到安全避免被人預測的場景下,還是要使用crypto/rand 包。 包級別的函數比如Int是線程安全的,但是如果你自己生成一個Rand對象,那么就要注意了,因為Rand對象是非線程安全的。

包級別的函數

func ExpFloat64() float64
func Float32() float32
func Float64() float64
func Int() int
func Int32() int32
func Int32N(n int32) int32
func Int64() int64
func Int64N(n int64) int64
func IntN(n int) int
func N[Int intType](n Int "Int intType") Int
func NormFloat64() float64
func Perm(n int) []int
func Shuffle(n int, swap func(i, j int))
func Uint32() uint32
func Uint32N(n uint32) uint32
func Uint64() uint64
func Uint64N(n uint64) uint64
func UintN(n uint) uint

針對int32、int64、uint32、uint64,分別有Xxxxx()和XxxxxN()兩種函數,前者返回一個隨機數,后者返回一個范圍在[0,n)的隨機數。

Float32和Float64返回范圍在[0.0, 1.0)的隨機浮點數。

IntN返回一個范圍在[0,n)的隨機數,數據類型是int類型。

N是一個泛型的函數,返回一個范圍在[0,n)的隨機數,底層數據是int類型的,特別適合time.Duration這樣的類型。

Perm返回一個長度為n的隨機排列的int數組。

Shuffle洗牌算法

NormFloat64返回一個標準正態分布的隨機數。

ExpFloat64返回一個指數分布的隨機數。

三種偽隨機數生成器

ChaCha8 也是包級別的函數使用的偽隨機數生成器。

type ChaCha8
func NewChaCha8(seed [32]byte) *ChaCha8
func (c *ChaCha8) MarshalBinary() ([]byte, error)
func (c *ChaCha8) Seed(seed [32]byte)
func (c *ChaCha8) Uint64() uint64
func (c *ChaCha8) UnmarshalBinary(data []byte) error

PCG 是另外一種偽隨機數生成器。

type PCG
func NewPCG(seed1, seed2 uint64) *PCG
func (p *PCG) MarshalBinary() ([]byte, error)
func (p *PCG) Seed(seed1, seed2 uint64)
func (p *PCG) Uint64() uint64
func (p *PCG) UnmarshalBinary(data []byte) error

Zipf是生成Zipf分布的偽隨機數生成器。

type Zipf
func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf
func (z *Zipf) Uint64() uint64

相信后續還會有一些第三方的偽隨機數生成器出現。

它們都實現了接口Source,Source接口只有一個方法Uint64():

type Source interface {
 Uint64() uint64
}

所有的偽隨機數生成器都可以包裝成一個Rand對象,Rand對象是非線程安全的,所以要注意。

func New(src Source) *Rand

這和Rust中的實現模式類似。<>第一版把它叫做伴型特性,第二版中不知道為什么把這一節去掉了。

Rust中的Rng類似這里的Go的Source,可以有多種實現生成器。Rust中的Rand也類似這里Go的Rand,基于Uint64() uint64提供各種類型的隨機數。

Rand提供了各種便利的方法,這些方法其實和包級別的函數是一樣的,只是它們是Rand對象的方法而已:

func (r *Rand) Float32() float32
func (r *Rand) Float64() float64
func (r *Rand) Int() int
func (r *Rand) Int32() int32
func (r *Rand) Int32N(n int32) int32
func (r *Rand) Int64() int64
func (r *Rand) Int64N(n int64) int64
func (r *Rand) IntN(n int) int
func (r *Rand) NormFloat64() float64
func (r *Rand) Perm(n int) []int
func (r *Rand) Shuffle(n int, swap func(i, j int))
func (r *Rand) Uint32() uint32
func (r *Rand) Uint32N(n uint32) uint32
func (r *Rand) Uint64() uint64
func (r *Rand) Uint64N(n uint64) uint64
func (r *Rand) UintN(n uint) uint

參考資料

[1]Go 1.22 release notes: https://tip.golang.org/doc/go1.22

[2]交互式運行新特性代碼的網頁: https://antonz.org/go-1-22/

[3]#20661: https://github.com/golang/go/issues/20661

[4]#21835: https://github.com/golang/go/issues/21835

[5]#26263: https://github.com/golang/go/issues/26263

[6]#60751: https://github.com/golang/go/discussions/60751

[7]#61716: https://github.com/golang/go/issues/61716

[8]Lemire: https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction

責任編輯:武曉燕 來源: 愛發白日夢的后端
相關推薦

2024-01-25 09:10:10

GoRust標準庫

2023-05-11 08:14:58

國產數據庫用戶

2023-12-08 08:38:15

EventLoopAPI瀏覽器

2024-01-08 20:05:32

2023-06-09 07:18:03

開源數據庫

2024-03-27 13:33:00

MySQLInnoDB事務

2024-05-30 08:19:52

微服務架構大型應用

2023-06-14 17:56:54

2022-04-07 11:15:22

PulseEventAPI函數

2022-12-30 08:35:00

2023-04-26 00:00:00

框架Vue.js客戶

2022-10-10 18:38:56

inert屬性鍵盤

2023-06-08 09:55:03

冪等計算機系統

2023-12-28 08:43:28

前端算法搜索

2022-10-19 08:19:32

動態基線預警

2023-11-06 07:37:01

函數式插槽React

2022-05-31 07:32:19

JDK8API工具

2024-08-28 13:09:50

2023-12-06 08:01:03

CSSPostCSS

2022-10-24 20:25:40

云原生SpringJava
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人精品一区二区三 | 国产一区二区a | 天天综合亚洲 | 九九热精品在线 | 国产精久久久久久久妇剪断 | 中文字幕视频在线看 | 久热爱 | 一区二区三区精品视频 | 日韩一区二区三区视频 | 亚洲视频免费 | 久在线视频 | 国产一区999 | 久青草影院 | 久久精品一区二区视频 | 欧美一级观看 | 成人在线视频一区 | 毛片网站在线观看 | 国产精品永久久久久久久www | 国产精品日韩欧美 | 91精产国品一二三区 | 午夜视频一区二区三区 | 国产一区二区三区四区三区四 | 久久久亚洲一区 | 夜夜草| 日本成人免费网站 | 成人在线中文字幕 | 国产黄色在线观看 | 国产一区久久 | 91在线中文字幕 | 精品一区av| 亚洲色图图片 | 九九热免费视频在线观看 | 91精品国产综合久久久久 | 成人欧美一区二区三区视频xxx | av资源中文在线 | 亚洲欧美精品 | 成人在线黄色 | 免费视频一区二区 | 欧美国产视频 | 亚洲成人一区二区三区 | 国产精品久久久久久久久污网站 |