Go言語で乱数のシードを設定する方法|rand.Seedは非推奨
![](https://tech.aru-zakki.com/wp-content/uploads/2024/01/RandSeed.001.jpeg)
Go1.20からrand.Seed()
で乱数を初期化するのは非推奨となったようです。この記事では、大体手段のrand.New(rand.NewSource(seed))
の使い方を説明します
rand.Seedでワーニング
VSCodeでrand.Seed()
で以下のようなワーニングが出るようになりました。
![VSCodeのワーニング](https://tech.aru-zakki.com/wp-content/uploads/2024/01/image-7-1024x295.png)
一番上に書かれている行を抜粋したのが以下になります。
rand.Seed is deprecated: As of Go 1.20 there is no reason to call Seed with a random value. Programs that call Seed with a known value to get a specific sequence of results should use New(NewSource(seed)) to obtain a local random generator.
これを読むと、Go1.20からSeedを呼ぶのではなく、New(NewSource(seed))
を使うようにということらしいです。
ということで、rand.Seed()
を使わない方法を紹介します。
rand.New(NewSource(Seed))
を使った乱数発生
rand.New(rand.NewSource(seed))
では、乱数ジェネレータを作成して乱数を発生させます。以下、seedを設定する場合と、time関数で設定する方法の2つを紹介します。
seedを設定する場合
rand.New
で乱数ジェネレータを作成し、作成したジェネレータを使って乱数を発生させます(r.Intn
の部分)
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
var r *rand.Rand
r = rand.New(rand.NewSource(42))
fmt.Println(r.Intn(10))
}
time関数を利用して乱数を発生させる場合
time関数をSeedに使う場合は、以下のようにします。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
var r *rand.Rand
r = rand.New(rand.NewSource(time.Now().UnixNano()))
fmt.Println(r.Intn(10))
}
Goのrand.Randの関数の一覧
以下、rand.Rand
で発生できる乱数の一覧(関数一覧)です。
関数名 | 説明 |
Float32() | 半開区間 [0.0,1.0) の擬似乱数を float32 として返す |
Float64() | 半開区間 [0.0,1.0) の擬似乱数を float64 として返す |
Int() | 負でない疑似乱数 int を返す |
Intn(n int) | 半開区間 [0,n) の非負の擬似乱数を int として返す |
Int31() | 非負の擬似ランダム 31 ビット整数を int32 として返す |
Int31n(n int32) | 半開区間 [0,n) の非負の擬似乱数を int32 として返す |
Int63() | 負でない疑似ランダム 63 ビット整数を int64 として返す |
Int63n(n int64) | 半開区間 [0,n) の非負の擬似乱数を int64 として返す |
NormFloat64() | 標準正規分布 (平均 = 0、標準偏差 = 1) で、-math.MaxFloat64 から +math.MaxFloat64 までの範囲の正規分布した float64 を返す |
Perm(n int) | n 個の整数のスライスとして、半開区間 [0,n) の整数の擬似ランダム順列を返す |
Shuffle(n int, swap func(i, j int)) | 要素の順序を擬似ランダム化する |
Uint32() | 疑似ランダム 32 ビット値を uint32 として返す |
Uint64() | 疑似ランダム 64 ビット値を uint64 として返す |
Shuffleが結構面白いので、少し紹介します。
Go言語のrand.Shuffleの使い方
Shuffleの定義は、Shuffle(n int, swap func(i, j int))
となっていて、配列などを渡す部分がありません。どうやって使うかというと、以下のようになります。
func()
の部分に、処理を書く形です。
package main
import (
"fmt"
"math/rand"
)
func main() {
var r *rand.Rand
r = rand.New(rand.NewSource(42))
const N = 10
a := make([]int, 0)
for i := 0; i < N; i++ {
a = append(a, i)
}
fmt.Println(a)
// [0 1 2 3 4 5 6 7 8 9]
r.Shuffle(N, func(i, j int) {
a[i], a[j] = a[j], a[i]
})
fmt.Println(a)
// [2 5 7 9 6 8 1 4 0 3]
}
わかりにくいですが、応用が効きます。例えば5~9まで(5以上の値)をシャッフルしたくない場合は、以下のように記述すれば実現できます。
r.Shuffle(N, func(i, j int) {
if i < 5 && j < 5 {
a[i], a[j] = a[j], a[i]
}
})
fmt.Println(a)
// [2 0 4 3 1 5 6 7 8 9]
if
文により5未満しか置換されないため、結果として0~4まではシャッフルされ、5以上はシャッフルされません。
![](https://tech.aru-zakki.com/wp-content/uploads/2023/06/tabbycat.png)
応用範囲は広いと思います
まとめ
VSCodeでrand.Seedでワーニングが出たので、ワーニングの理由と代替手段について調べてみましたので紹介しました。