snippetgoCritical
How to properly seed random number generator
Viewed 0 times
properlyhowrandomnumbergeneratorseed
Problem
I am trying to generate a random string in Go and here is the code I have written so far:
My implementation is very slow. Seeding using
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)
}My implementation is very slow. Seeding using
time brings the same random number for a certain time, so the loop iterates again and again. How can I improve my code?Solution
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
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
Move the
UnixNano returns t as a Unix time, the number of nanoseconds elapsed since January 1, 1970 UTC.
Note also that I think you can simplify your string building:
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. And lose the .UTC() call since:UnixNano returns t as a Unix time, the number of nanoseconds elapsed since January 1, 1970 UTC.
Note also that I think you can simplify your string building:
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)
}Code Snippets
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)
}Context
Stack Overflow Q#12321133, score: 301
Revisions (0)
No revisions yet.