rand seed using 'time.Now().Unix()' consequence mass common rand numbers, but using unixNano as the seed will not ,how to choose the rand's seed between 'time.Now().Unix()' and 'time.Now().UnixNano()' ?

482 views
Skip to first unread message

Chou Yan

unread,
Jun 26, 2019, 10:17:08 PM6/26/19
to golang-nuts
I use:
r:=rand.New(rand.NewSource(time.Now().Unix()))
r..Intn(96)
I got:

and val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 39
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
rand val: 82
...
mass common sequential number .
But if I change that:
r:=rand.New(rand.NewSource(time.Now().UnixNano()))
It will not happen.
Why does this happened? and how do I choose it between time.Now().Unix() or UnixNano()?

Kurtis Rader

unread,
Jun 26, 2019, 10:31:51 PM6/26/19
to Chou Yan, golang-nuts
On Wed, Jun 26, 2019 at 7:17 PM Chou Yan <yan.cho...@gmail.com> wrote:
I use:
r:=rand.New(rand.NewSource(time.Now().Unix()))
r..Intn(96)

That isn't valid Go. Which `rand` package? The one in package `crypto` or `math`? What the heck is `r..Intn(96)`?  Please post a minimal, complete, example that compiles and runs at https://play.golang.org.

--
Kurtis Rader
Caretaker of the exceptional canines Junior and Hank

Burak Serdar

unread,
Jun 26, 2019, 10:32:38 PM6/26/19
to Chou Yan, golang-nuts
On Wed, Jun 26, 2019 at 8:17 PM Chou Yan <yan.cho...@gmail.com> wrote:
>
> I use:
> r:=rand.New(rand.NewSource(time.Now().Unix()))
> r..Intn(96)

How are you generating multiple random numbers? If your loop that
generates these numbers include the r:=rand.New(...), then you're
essentially seeding the random number generator with the same number,
because the program ends before time.Now().Unix() returns a different
value every second.

Move the r:=rand.New(...) outsite the for loop.
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/ce0671c5-f2df-42d9-a7af-bdef939e6d6d%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Chou Yan

unread,
Jun 26, 2019, 10:48:23 PM6/26/19
to golang-nuts
like this:
r:=rand.New(rand.NewSource(time.Now().Unix())) 
for {
    r.Intn(96) 
}
I know the same seed will generate the same sequence. But I don't know why it generate mass same number when I use seed of 'time.Now().Unix()', But when I use seed of 'time.Now().UnixNano()', It will not.
I suspect what this is related to the seqence rand algorithm,But I have no relevant evidence

在 2019年6月27日星期四 UTC+8上午10:32:38,Burak Serdar写道:
> To unsubscribe from this group and stop receiving emails from it, send an email to golan...@googlegroups.com.

Burak Serdar

unread,
Jun 26, 2019, 10:52:56 PM6/26/19
to Chou Yan, golang-nuts
On Wed, Jun 26, 2019 at 8:48 PM Chou Yan <yan.cho...@gmail.com> wrote:
>
> like this:
> r:=rand.New(rand.NewSource(time.Now().Unix()))
> for {
> r.Intn(96)
> }
> I know the same seed will generate the same sequence. But I don't know why it generate mass same number when I use seed of 'time.Now().Unix()', But when I use seed of 'time.Now().UnixNano()', It will not.
> I suspect what this is related to the seqence rand algorithm,But I have no relevant evidence

This doesn't make sense. Can you reproduce it in the go playground?
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/99351298-7843-4556-b422-8635eb96c936%40googlegroups.com.

Kurtis Rader

unread,
Jun 26, 2019, 11:07:28 PM6/26/19
to Chou Yan, golang-nuts
Works for me: https://play.golang.org/p/zD5F7gp41re

Like Burak I suspect you are initializing the RNG in a tight loop. Since `time.Now().Unix()` has a resolution of one second you end up generating the same initial value every time through the loop until the current time advances to the next second.

To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/99351298-7843-4556-b422-8635eb96c936%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Chou Yan

unread,
Jun 26, 2019, 11:16:01 PM6/26/19
to golang-nuts
The situation I am currently experiencing is that it only occur on my online app. I try it at local but I can not got the result. 
haha... I make a mistake.
the code is :

func WeightRandom(services []*registry.Service) Next{
w := weighted.NewRandW()
for _, service := range services {
for _,n := range service.Nodes {
w.Add(n,n.Weight)
}
}
return func() (*registry.Node, error) {
n := w.Next()
no, ok := n.(*registry.Node)
if !ok {
return nil,errors.New("get next err")
}
return no, nil
}
}

The 'rand.New(...SEED)' is outside the loop of for But I neglect that this func 'WeightRandom' will be mass goroutine call. so each time.Now().Unix() ,the same seed ,the same sequence. So I got mass common rand number.But when I change it as time.Now().UnixNano(), the seed will not be the same because of the unixnano. so I got correctly. thank you very much

在 2019年6月27日星期四 UTC+8上午10:52:56,Burak Serdar写道:

Chou Yan

unread,
Jun 26, 2019, 11:18:25 PM6/26/19
to golang-nuts
I fix it by :

var w = weighted.NewRandW()

func WeightRandom(services []*registry.Service) Next{
for _, service := range services {
for _,n := range service.Nodes {
w.Add(n,n.Weight)
}
}
return func() (*registry.Node, error) {
n := w.Next()
no, ok := n.(*registry.Node)
if !ok {
return nil,errors.New("get next err")
}
return no, nil
}
}

thx

在 2019年6月27日星期四 UTC+8上午11:16:01,Chou Yan写道:

Chou Yan

unread,
Jun 26, 2019, 11:21:56 PM6/26/19
to golang-nuts
thx. you are right. I make a mistake. I negleck that my func will be called by mass goroutine, it will get the same seed and the same sequence

在 2019年6月27日星期四 UTC+8上午11:07:28,Kurtis Rader写道:
Works for me: https://play.golang.org/p/zD5F7gp41re

Like Burak I suspect you are initializing the RNG in a tight loop. Since `time.Now().Unix()` has a resolution of one second you end up generating the same initial value every time through the loop until the current time advances to the next second.

Kurtis Rader

unread,
Jun 26, 2019, 11:22:49 PM6/26/19
to Chou Yan, golang-nuts
On Wed, Jun 26, 2019 at 8:18 PM Chou Yan <yan.cho...@gmail.com> wrote:
I fix it by :

var w = weighted.NewRandW()

Insufficient context to understand what that does. Let alone how it "fixes" the problem since you haven't shown us your `NewRandW()` function. In general you should never initialize a RNG more than once unless you are doing so to create a reproducible sequence of values. In which case you should be initializing it with a constant value rather than a pseudo-random value like `time.Now().Unix()`.

Chou Yan

unread,
Jun 26, 2019, 11:29:53 PM6/26/19
to golang-nuts
It's the context:

// NewRandW creates a new RandW with a random object.
func NewRandW() *RandW {
return &RandW{r: rand.New(rand.NewSource(time.Now().Unix()))}
}

n := w.Next()

// Next returns next selected item.
func (rw *RandW) Next() (item interface{}) {
...
randomWeight := rw.r.Intn(rw.sumOfWeights)
//fmt.Printf("rand val: %d\n",randomWeight)
...
}

I am sorry about that I did't give the context of my code.

在 2019年6月27日星期四 UTC+8上午11:22:49,Kurtis Rader写道:

Kurtis Rader

unread,
Jun 26, 2019, 11:40:58 PM6/26/19
to Chou Yan, golang-nuts
On Wed, Jun 26, 2019 at 8:30 PM Chou Yan <yan.cho...@gmail.com> wrote:
// NewRandW creates a new RandW with a random object.
func NewRandW() *RandW {
return &RandW{r: rand.New(rand.NewSource(time.Now().Unix()))}
}

That is broken even if you use `UnixNano()`. Repeat after me: In general you should never initialize a RNG more than once. I say "in general" because there are use cases where reproducible results require doing so. But those use cases do not seem to be applicable to your situation. Without knowing more about why you are creating multiple RNGs the general advice is create a single RNG and use it every place you need a random number. You should probably be using `rand.Seed()` and `rand.Source()` rather than `rand.NewSource()` given your fundamental misunderstanding about how RNGs work.
Reply all
Reply to author
Forward
0 new messages