How to properly seed random number generator

前端 未结 9 1107
陌清茗
陌清茗 2020-11-28 20:25

I am trying to generate a random string in Go and here is the code I have written so far:

package main

import (
    \"bytes\"
    \"fmt\"
    \"math/rand\"
         


        
相关标签:
9条回答
  • 2020-11-28 20:40

    @[Denys Séguret] has posted correct. But In my case I need new seed everytime hence below code;

    Incase you need quick functions. I use like this.

    
    func RandInt(min, max int) int {
        r := rand.New(rand.NewSource(time.Now().UnixNano()))
        return r.Intn(max-min) + min
    }
    
    func RandFloat(min, max float64) float64 {
        r := rand.New(rand.NewSource(time.Now().UnixNano()))
        return min + r.Float64()*(max-min)
    }
    
    

    source

    0 讨论(0)
  • 2020-11-28 20:53

    If your aim is just to generate a sting of random number then I think it's unnecessary to complicate it with multiple function calls or resetting seed every time.

    The most important step is to call seed function just once before actually running rand.Init(x). Seed uses the provided seed value to initialize the default Source to a deterministic state. So, It would be suggested to call it once before the actual function call to pseudo-random number generator.

    Here is a sample code creating a string of random numbers

    package main 
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    
    
    func main(){
        rand.Seed(time.Now().UnixNano())
    
        var s string
        for i:=0;i<10;i++{
        s+=fmt.Sprintf("%d ",rand.Intn(7))
        }
        fmt.Printf(s)
    }
    

    The reason I used Sprintf is because it allows simple string formatting.

    Also, In rand.Intn(7) Intn returns, as an int, a non-negative pseudo-random number in [0,7).

    0 讨论(0)
  • 2020-11-28 20:58

    Each time you set the same seed, you get the same sequence. So of course if you're setting the seed to the time in a fast loop, you'll probably call it with the same seed many times.

    In your case, as you're calling your randInt function until you have a different value, you're waiting for the time (as returned by Nano) to change.

    As for all pseudo-random libraries, you have to set the seed only once, for example when initializing your program unless you specifically need to reproduce a given sequence (which is usually only done for debugging and unit testing).

    After that you simply call Intn to get the next random integer.

    Move the rand.Seed(time.Now().UTC().UnixNano()) line from the randInt function to the start of the main and everything will be faster.

    Note also that I think you can simplify your string building:

    package main
    
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    func main() {
        rand.Seed(time.Now().UTC().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)
    }
    
    0 讨论(0)
  • 2020-11-28 20:59

    Small update due to golang api change, please omit .UTC() :

    time.Now().UTC().UnixNano() -> time.Now().UnixNano()

    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    func main() {
        rand.Seed(time.Now().UnixNano())
        fmt.Println(randomInt(100, 1000))
    }
    
    func randInt(min int, max int) int {
        return min + rand.Intn(max-min)
    }
    
    0 讨论(0)
  • 2020-11-28 21:01

    just to toss it out for posterity: it can sometimes be preferable to generate a random string using an initial character set string. This is useful if the string is supposed to be entered manually by a human; excluding 0, O, 1, and l can help reduce user error.

    var alpha = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"
    
    // generates a random string of fixed size
    func srand(size int) string {
        buf := make([]byte, size)
        for i := 0; i < size; i++ {
            buf[i] = alpha[rand.Intn(len(alpha))]
        }
        return string(buf)
    }
    

    and I typically set the seed inside of an init() block. They're documented here: http://golang.org/doc/effective_go.html#init

    0 讨论(0)
  • 2020-11-28 21:02

    OK why so complex!

    package main
    
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    func main() {
        rand.Seed( time.Now().UnixNano())
        var bytes int
    
        for i:= 0 ; i < 10 ; i++{ 
            bytes = rand.Intn(6)+1
            fmt.Println(bytes)
            }
        //fmt.Println(time.Now().UnixNano())
    }
    

    This is based off the dystroy's code but fitted for my needs.

    It's die six (rands ints 1 =< i =< 6)

    func randomInt (min int , max int  ) int {
        var bytes int
        bytes = min + rand.Intn(max)
        return int(bytes)
    }
    

    The function above is the exactly same thing.

    I hope this information was of use.

    0 讨论(0)
提交回复
热议问题