75

All the integer functions in math/rand generate non-negative numbers.

rand.Int() int // [0, MaxInt] rand.Int31() int32 // [0, MaxInt32] rand.Int31n(n int32) int32 // [0, n) rand.Int63() int64 // [0, MaxInt64] rand.Int63n(n int64) int64 // [0, n) rand.Intn(n int) int // [0, n) 

I would like to generate random numbers in the range [-m, n). In other words, I would like to generate a mix of positive and negative numbers.

2
  • Your specification of range may be obvious to you and may be mathematically unambiguous, but most people are heavily attracted by symmetry, so many will think of the interval [min,max]. Well, maybe a matter of taste... Commented Dec 22, 2016 at 12:33
  • 1
    In other words: Your mix of positive and negative numbers will be unbalanced. Commented Dec 22, 2016 at 12:37

9 Answers 9

122

For Go 1.22+:

Use the math/rand/v2 package.

import "math/rand/v2" func randRange(min, max int) int { return rand.IntN(max-min) + min } 

For Go 1.21 and earlier:

import "math/rand" func randRange(min, max int) int { return rand.Intn(max-min) + min } 

Please note that this returns numbers in the range [min, max), meaning that max is never returned. For example, randRange(1, 3) would return 1 and 2 only. It would never return 3. If you want numbers in the range [min, max], just add 1 as shown below:

return rand.IntN(max+1-min) + min 
Sign up to request clarification or add additional context in comments.

7 Comments

rand.Intn(2 - 1) + 1 will always return 1
The question asks for random numbers in the range [min, max). The only number in range [1, 2) is 1.
@TimoHuovinen range [min, max)
import "math/rand"
Thank you @IStranger! I've updated my answer to remove the deprecated rand.Seed() call.
|
21

This will generate random numbers within given range [a, b]

rand.Seed(time.Now().UnixNano()) n := a + rand.Intn(b-a+1) 

source

3 Comments

This is the simplest answer that actually gives you the maximum value.
For clarity a = min and b = max. Maybe obvious to some but it tripped me out
It's no longer necessary to see the random number generator before calling rand.Intn
11

As to prevent repeating min and max over and over again, I suggest to switch range and random in thinking about it. This is what I found to work as expected:

package main import ( "fmt" "math/rand" ) // range specification, note that min <= max type IntRange struct { min, max int } // get next random value within the interval including min and max func (ir *IntRange) NextRandom(r* rand.Rand) int { return r.Intn(ir.max - ir.min +1) + ir.min } func main() { r := rand.New(rand.NewSource(55)) ir := IntRange{-1,1} for i := 0; i<10; i++ { fmt.Println(ir.NextRandom(r)) } } 

See on Go Playground

Specifying the range

The solution you found in the Cookbook misses to exactly specify how min and max work, but of course it meets your specification ([-min, max)). I decided to specify the range as a closed interval ([-min, max], that means its borders are included in the valid range). Compared to my understanding of the Cookbook description:

gives you that random number within any two positive numbers that you specify (in this case, 1 and 6).

(which can be found below the code snippet in the Golang Cookbook)

the Cookbook implementation is off by one (which of course brings it in good company with lots of programs that are helpful at first glance).

4 Comments

Good catch, @Wolf--I noticed the same issue with the Cookbook example. (This should have more votes, but the upvoters appear to have left SO a long time ago.)
...well, you are still here ;) I think that my variation should be understood as a side note because the OP explicitly referred to the range [-m, n) which is the understanding of ranges that is most common to programmers, mostly not to users... BTW: isolating the interval may be interesting, sometimes helpful, but definitely challenging for good naming: Today, I'm a little bit confused about IntRanges that produce NextRandom values.
it returns always the same results play.golang.org/p/pXZvtcmxjOq
@rok The implementation of the go playground fakes the time, see Inside the Go Playground - The Go Blog for the details, so I decided to go that way instead of failing on fake randomization
2

A small utility I wrote for generating random slices(very much like python range)

Code - https://github.com/alok87/goutils/blob/master/pkg/random/random.go

import "github.com/alok87/goutils/pkg/random" random.RangeInt(2, 100, 5) [3, 10, 30, 56, 67] 

1 Comment

it's always returning the same numbers play.golang.org/p/oO6nBlQdWTX
2

Solution that worked for me is: j = rand.Intn(600) - 100 where m is 100 and n is 500, it will generate numbers from -100 to 499.

Comments

2

This worked for me (Generate random number between 1 and 10)...

import "math/rand" rand.Seed(time.Now().UnixNano()) randId := rand.Intn(10-1) + 1 

Comments

0

I solved this problem using for cycle. For example, you need to generate a number between 50 and 100:

val := rand.Intn(100) + 1 // determined the upper bound of the cycle for val < 50 { val = rand.Intn(100) + 1} // repeat the generation if the number is less than 50 

Comments

0

I agree with @Wolf's answer, however I'd add more OOP-alike style like that:

package main import ( "math/rand" "sync" "time" ) type Random struct { source rand.Source mu sync.Mutex } func (rnd *Random) Next(from int, to int) int { rnd.mu.Lock() if rnd.source == nil { rnd.source = rand.NewSource(time.Now().UnixNano()) } rnd.mu.Unlock() return from + rand.New(rnd.source).Intn(to-from+1) } func main() { rnd := Random{} println(rnd.Next(1, 100)) } 

Comments

0

The question asks how to generate random numbers between min and max where max is not inclusive meaning max will never be reached.

For example, if min is 1 and max is 4 then it would only give you values from 1-3.

If you came here looking how to generate all numbers in min and max range then you need to adjust for that by adding +1.

rand.Intn(max + 1 - min) + min 

Example of it working by showing which numbers were hit and how many times:

package main import ( "fmt" "math/rand" ) func main() { dat := make(map[int]int) for i := 0; i < 100000; i++ { x := getRandomInt(1, 4) dat[x] += 1 } fmt.Println(dat) } func getRandomInt(min, max int) int { return rand.Intn(max + 1 - min) + min } 

Output:

map[1:24810 2:25194 3:25024 4:24972] 

You can also randomly generate negative numbers. If we made min -5 and max 5 we get:

Output:

map[-5:9302 -4:9121 -3:9136 -2:8951 -1:9116 0:8928 1:9156 2:8970 3:9188 4:9045 5:9087] 

2 Comments

You’re correct that max is never reached. The question asks for random numbers in the range [min, max). The ) means the upper bound is noninclusive.
Thanks for pointing that out. Will update the answer accordingly. Landed here from Google search on random numbers so I think this answer is still helpful for other people looking to include max in their range.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.