1. ホーム
  2. random

[解決済み】乱数生成器の適切なシード方法

2022-04-12 01:39:33

質問

私はGoでランダムな文字列を生成しようとしており、以下は私がこれまでに書いたコードです。

package main

import (
    "bytes"
    "fmt"
    "math/rand"
    "time"
)

func main() {
    fmt.Println(randomString(10))
}

func randomString(l int) string {
    var result bytes.Buffer
    var temp string
    for i := 0; i < l; {
        if string(randInt(65, 90)) != temp {
            temp = string(randInt(65, 90))
            result.WriteString(temp)
            i++
        }
    }
    return result.String()
}

func randInt(min int, max int) int {
    rand.Seed(time.Now().UTC().UnixNano())
    return min + rand.Intn(max-min)
}

私の実装は非常に遅いです。を使ったシード time は一定時間同じ乱数を持ってくるので、ループが何度も繰り返されます。どうすれば改善できるでしょうか?

どのように解決するのですか?

同じシードを設定するたびに、同じシーケンスになります。だから当然、高速ループで時刻にシードをセットしている場合は、何度も同じシードで呼び出すことになるのだろう。

あなたの場合、あなたの randInt 関数は、異なる値を取得するまで、(Nano が返す)時間が変わるのを待っています。

すべての擬似乱数ライブラリと同様 特にシーケンスを再現する必要がない限り(通常、デバッグやユニットテストのためにのみ行われます)、例えばプログラムの初期化時に一度だけシードを設定する必要があります。

その後、単純に Intn で次の乱数値を取得します。

を移動させます。 rand.Seed(time.Now().UTC().UnixNano()) の行を、randInt 関数から main の先頭に移動させると、すべてが高速になります。そして .UTC() を呼び出してからです。

UnixNanoはtをUnix時間として、1970年UTC1月1日から経過したナノ秒の数を返します。

また、文字列のビルドを簡略化することができると思うので、注意してください。

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())
    fmt.Println(randomString(10))
}

func randomString(l int) string {
    bytes := make([]byte, l)
    for i := 0; i < l; i++ {
        bytes[i] = byte(randInt(65, 90))
    }
    return string(bytes)
}

func randInt(min int, max int) int {
    return min + rand.Intn(max-min)
}