Generating Random Numbers in Go - random

I am trying to generate random numbers (integers) in Go, to no avail. I found the rand package in crypto/rand, which seems to be what I want, but I can't tell from the documentation how to use it. This is what I'm trying right now:
b := []byte{}
something, err := rand.Read(b)
fmt.Printf("something = %v\n", something)
fmt.Printf("err = %v\n", err)
But unfortunately this always outputs:
something = 0
err = <nil>
Is there a way to fix this so that it actually generates random numbers? Alternatively, is there a way to set the upper bound on the random numbers this generates?

Depending on your use case, another option is the math/rand package. Don't do this if you're generating numbers that need to be completely unpredictable. It can be helpful if you need to get results that are reproducible, though -- just pass in the same seed you passed in the first time.
Here's the classic "seed the generator with the current time and generate a number" program:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().Unix())
fmt.Println(rand.Int())
}

crypto/rand provides only binary stream of random data, but you can read integers from it using encoding/binary:
package main
import "encoding/binary"
import "crypto/rand"
func main() {
var n int32
binary.Read(rand.Reader, binary.LittleEndian, &n)
println(n)
}

As of 1 april 2012, after the release of the stable version of the lang, you can do the following:
package main
import "fmt"
import "time"
import "math/rand"
func main() {
rand.Seed(time.Now().UnixNano()) // takes the current time in nanoseconds as the seed
fmt.Println(rand.Intn(100)) // this gives you an int up to but not including 100
}

You can also develop your own random number generator, perhaps based upon a simple "desert island PRNG", a Linear Congruential Generator. Also, look up L'Ecuyer (1999), Mersenne Twister, or Tausworthe generator...
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
(Avoid RANDU, it was popular in the 1960's, but the random numbers generated fall on 15 hyperplanes in 3-space).
package pmPRNG
import "errors"
const (
Mersenne31 = 2147483647 // = 2^31-1
Mersenne31Inv = 1.0 / 2147483647.0 // = 4.656612875e-10
// a = 16807
a = 48271
)
// Each stream gets own seed
type PRNGStream struct {
state int
}
func PRNGStreamNew(seed int) *PRNGStream {
prng := (&PRNGStream{})
prng.SetSeed(seed)
return prng
}
// enforce seed in [1, 2^31-1]
func (r*PRNGStream) SetSeed(seed int) error {
var err error
if seed < 1 || seed > Mersenne31 {
err = errors.New("Seed OOB")
}
if seed > Mersenne31 { seed = seed % Mersenne31 }
if seed < 1 { seed = 1 }
r.state = seed
return err
}
// Dig = Park-Miller DesertIslandGenerator
// integer seed in [1, 2^31-1]
func (r*PRNGStream) Dig(seed int) float32 {
xprev := r.state // x[i-1]
xnext := (a * xprev) % Mersenne31 // x[i] = (a*x[i-1])%m
r.state = xnext // x[i-1] = x[i]
Ri := float32(xnext) * Mersenne31Inv // convert Ui to Ri
return Ri
}
func (r*PRNGStream) Rand() float32 {
r.state = (uint64_t)*r.state * Multby % 0x7fffffff
return float32(r.state) * Mersenne31Inv
}
A few relevant links:
https://en.wikipedia.org/wiki/Lehmer_random_number_generator
You might use this function to update your x[i+1], instead of the one above,
val = ((state * 1103515245) + 12345) & 0x7fffffff
(basically, different values of a, c, m)
https://www.redhat.com/en/blog/understanding-random-number-generators-and-their-limitations-linux
https://www.iro.umontreal.ca/~lecuyer/myftp/papers/handstat.pdf
https://www.math.utah.edu/~alfeld/Random/Random.html
https://learn.microsoft.com/en-us/archive/msdn-magazine/2016/august/test-run-lightweight-random-number-generation

Related

Generate random float64 numbers in specific range using Golang

package main
import (
"fmt"
"math/rand"
"time"
)
func genRandNums(min, max float64) []float64 {
var randNums []float64
s := rand.NewSource(time.Now().Unix())
r := rand.New(s)
for x := 0; x < 10; x++ {
// generate random float in range of min and max inclusive, append
// to randNums and return randNums
}
return randNums
}
func main() {
nums := genRandNums(1.10, 101.98)
fmt.Println(nums)
}
I have tried searching online on how to accomplish this, but I only found out how to generate random integers in a range. Is there any way I can generate random floats in a range using Go stdlib?
Simply use rand.Float64() to get a random number in the range of [0..1), and you can map (project) that to the range of [min..max) like this:
r := min + rand.Float64() * (max - min)
And don't create a new rand.Rand and / or rand.Source in your function, just create a global one or use the global one of the math/rand package. But don't forget to initialize it once.
Here's an example function doing that:
func randFloats(min, max float64, n int) []float64 {
res := make([]float64, n)
for i := range res {
res[i] = min + rand.Float64() * (max - min)
}
return res
}
Using it:
func main() {
rand.Seed(time.Now().UnixNano())
fmt.Println(randFloats(1.10, 101.98, 5))
}
Output (try it on the Go Playground):
[51.43243344285539 51.92791316776663 45.04754409242326 28.77642913403846
58.21730813384373]
Some notes:
The code on the Go playground will always give the same random numbers (time is fixed, so most likely the Seed will always be the same, also output is cached)
The above solution is safe for concurrent use, because it uses rand.Float64() which uses the global rand which is safe. Should you create your own rand.Rand using a source obtained by rand.NewSource(), that would not be safe and neither the randFloats() using it.
if you want to use crypto/rand, here is another go playground for RandomInt() and RandomFloat() generator (float uses RandomInt inside with constant precision - you can make it as parameter)
Go playground

How to use Math/Big in Go Lang

I am trying to create a factorial program, but when the numbers get too big the answer becomes wrong. Here is my code. I am new to math/big and cannot figure out how to correctly implement it into the program. Any help is appreciated. Thanks.
package main
import (
"fmt"
"os"
"strconv"
"math/big"
)
func main() {
fmt.Print("What integer would you like to to find a total factorial for?")
var userinput string
var userint int
fmt.Scan(&userinput)
userint, err := strconv.Atoi(userinput)
if err != nil {
fmt.Println("ERROR: Please input an integer")
os.Exit(2)
}
var efactorial int = 1
var ofactorial int = 1
var tfactorial int
var counter int
for counter = 2; counter <= userint; counter = counter + 2 {
efactorial = efactorial * counter
}
for counter = 1; counter <= userint; counter = counter + 2 {
ofactorial = ofactorial * counter
}
fmt.Println("Even factorial is: ", efactorial)
fmt.Println("Odd factorial is: ", ofactorial)
tfactorial = efactorial + ofactorial
fmt.Println("The Total factorial is: ", tfactorial)
}
You can use big.Int.MulRange to find the product of a range of integers. This is ideal for computing factorials. Here's a complete example that computes 50!
package main
import (
"fmt"
"math/big"
)
func main() {
var f big.Int
f.MulRange(1, 50)
fmt.Println(&f)
}
The output:
30414093201713378043612608166064768844377641568960512000000000000
you want ofactorial and tfactorial to be of type big.Int
ofactorial := big.NewInt(1)
tfactorial := big.NewInt(0)
Then you will want to use the methods from the big package for multiplying Ints found here
your for loop will look something like
for counter = 2; counter <= userint; counter = counter + 2 {
efactorial.Mul(efactorial * big.NewInt(counter))
}

How to generate a stream of *unique* random numbers in Go using the standard library

How can I generate a stream of unique random number in Go?
I want to guarantee there are no duplicate values in array a using math/rand and/or standard Go library utilities.
func RandomNumberGenerator() *rand.Rand {
s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
return r1
}
rng := RandomNumberGenerator()
N := 10000
for i := 0; i < N; i++ {
a[i] = rng.Int()
}
There are questions and solutions on how to generate a series of random number in Go, for example, here.
But I would like to generate a series of random numbers that does not duplicate previous values. Is there a standard/recommended way to achieve this in Go?
My guess is to (1) use permutation or to (2) keep track of previously generated numbers and regenerate a value if it's been generated before.
But solution (1) sounds like overkill if I only want a few number and (2) sounds very time consuming if I end up generating a long series of random numbers due to collision, and I guess it's also very memory-consuming.
Use Case: To benchmark a Go program with 10K, 100K, 1M pseudo-random number that has no duplicates.
You should absolutely go with approach 2. Let's assume you're running on a 64-bit machine, and thus generating 63-bit integers (64 bits, but rand.Int never returns negative numbers). Even if you generate 4 billion numbers, there's still only a 1 in 4 billion chance that any given number will be a duplicate. Thus, you'll almost never have to regenerate, and almost never never have to regenerate twice.
Try, for example:
type UniqueRand struct {
generated map[int]bool
}
func (u *UniqueRand) Int() int {
for {
i := rand.Int()
if !u.generated[i] {
u.generated[i] = true
return i
}
}
}
I had similar task to pick elements from initial slice by random uniq index. So from slice with 10k elements get 1k random uniq elements.
Here is simple head on solution:
import (
"time"
"math/rand"
)
func getRandomElements(array []string) []string {
result := make([]string, 0)
existingIndexes := make(map[int]struct{}, 0)
randomElementsCount := 1000
for i := 0; i < randomElementsCount; i++ {
randomIndex := randomIndex(len(array), existingIndexes)
result = append(result, array[randomIndex])
}
return result
}
func randomIndex(size int, existingIndexes map[int]struct{}) int {
rand.Seed(time.Now().UnixNano())
for {
randomIndex := rand.Intn(size)
_, exists := existingIndexes[randomIndex]
if !exists {
existingIndexes[randomIndex] = struct{}{}
return randomIndex
}
}
}
I see two reasons for wanting this. You want to test a random number generator, or you want unique random numbers.
You're Testing A Random Number Generator
My first question is why? There's plenty of solid random number generators available. Don't write your own, it's basically dabbling in cryptography and that's never a good idea. Maybe you're testing a system that uses a random number generator to generate random output?
There's a problem: there's no guarantee random numbers are unique. They're random. There's always a possibility of collision. Testing that random output is unique is incorrect.
Instead, you want to test the results are distributed evenly. To do this I'll reference another answer about how to test a random number generator.
You Want Unique Random Numbers
From a practical perspective you don't need guaranteed uniqueness, but to make collisions so unlikely that it's not a concern. This is what UUIDs are for. They're 128 bit Universally Unique IDentifiers. There's a number of ways to generate them for particular scenarios.
UUIDv4 is basically just a 122 bit random number which has some ungodly small chance of a collision. Let's approximate it.
n = how many random numbers you'll generate
M = size of the keyspace (2^122 for a 122 bit random number)
P = probability of collision
P = n^2/2M
Solving for n...
n = sqrt(2MP)
Setting P to something absurd like 1e-12 (one in a trillion), we find you can generate about 3.2 trillion UUIDv4s with a 1 in a trillion chance of collision. You're 1000 times more likely to win the lottery than have a collision in 3.2 trillion UUIDv4s. I think that's acceptable.
Here's a UUIDv4 library in Go to use and a demonstration of generating 1 million unique random 128 bit values.
package main
import (
"fmt"
"github.com/frankenbeanies/uuid4"
)
func main() {
for i := 0; i <= 1000000; i++ {
uuid := uuid4.New().Bytes()
// use the uuid
}
}
you can generate a unique random number with len(12) using UnixNano in golang time package :
uniqueNumber:=time.Now().UnixNano()/(1<<22)
println(uniqueNumber)
it's always random :D
1- Fast positive and negative int32 unique pseudo random numbers in 296ms using std lib:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
const n = 1000000
rand.Seed(time.Now().UTC().UnixNano())
duplicate := 0
mp := make(map[int32]struct{}, n)
var r int32
t := time.Now()
for i := 0; i < n; {
r = rand.Int31()
if i&1 == 0 {
r = -r
}
if _, ok := mp[r]; ok {
duplicate++
} else {
mp[r] = zero
i++
}
}
fmt.Println(time.Since(t))
fmt.Println("len: ", len(mp))
fmt.Println("duplicate: ", duplicate)
positive := 0
for k := range mp {
if k > 0 {
positive++
}
}
fmt.Println(`n=`, n, `positive=`, positive)
}
var zero = struct{}{}
output:
296.0169ms
len: 1000000
duplicate: 118
n= 1000000 positive= 500000
2- Just fill the map[int32]struct{}:
for i := int32(0); i < n; i++ {
m[i] = zero
}
When reading it is not in order in Go:
for k := range m {
fmt.Print(k, " ")
}
And this just takes 183ms for 1000000 unique numbers, no duplicate (The Go Playground):
package main
import (
"fmt"
"time"
)
func main() {
const n = 1000000
m := make(map[int32]struct{}, n)
t := time.Now()
for i := int32(0); i < n; i++ {
m[i] = zero
}
fmt.Println(time.Since(t))
fmt.Println("len: ", len(m))
// for k := range m {
// fmt.Print(k, " ")
// }
}
var zero = struct{}{}
3- Here is the simple but slow (this takes 22s for 200000 unique numbers), so you may generate and save it to a file once:
package main
import "time"
import "fmt"
import "math/rand"
func main() {
dup := 0
t := time.Now()
const n = 200000
rand.Seed(time.Now().UTC().UnixNano())
var a [n]int32
var exist bool
for i := 0; i < n; {
r := rand.Int31()
exist = false
for j := 0; j < i; j++ {
if a[j] == r {
dup++
fmt.Println(dup)
exist = true
break
}
}
if !exist {
a[i] = r
i++
}
}
fmt.Println(time.Since(t))
}
Temporary workaround based on #joshlf's answer
type UniqueRand struct {
generated map[int]bool //keeps track of
rng *rand.Rand //underlying random number generator
scope int //scope of number to be generated
}
//Generating unique rand less than N
//If N is less or equal to 0, the scope will be unlimited
//If N is greater than 0, it will generate (-scope, +scope)
//If no more unique number can be generated, it will return -1 forwards
func NewUniqueRand(N int) *UniqueRand{
s1 := rand.NewSource(time.Now().UnixNano())
r1 := rand.New(s1)
return &UniqueRand{
generated: map[int]bool{},
rng: r1,
scope: N,
}
}
func (u *UniqueRand) Int() int {
if u.scope > 0 && len(u.generated) >= u.scope {
return -1
}
for {
var i int
if u.scope > 0 {
i = u.rng.Int() % u.scope
}else{
i = u.rng.Int()
}
if !u.generated[i] {
u.generated[i] = true
return i
}
}
}
Client side code
func TestSetGet2(t *testing.T) {
const N = 10000
for _, mask := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314159} {
rng := NewUniqueRand(2*N)
a := make([]int, N)
for i := 0; i < N; i++ {
a[i] = (rng.Int() ^ mask) << 1
}
//Benchmark Code
}
}

Go Random number always return 168

I am a complete noob in regards to Go.
I am trying to make a an arbitrary function that returns two random numbers added together.
I have pasted my code below, and cannot figure out why it always returns 168!
package main
import(
"fmt"
"math/rand"
)
func add(x int, y int) int{
return x + y
}
var a int = rand.Intn(100)
var b int = rand.Intn(100)
func main() {
fmt.Println(add(a, b))
}
You have to specify seed to get different numbers. It is outlined in documentation:
Top-level functions, such as Float64 and Int, use a default shared
Source that produces a deterministic sequence of values each time a
program is run. Use the Seed function to initialize the default Source
if different behavior is required for each run.
And some reference about Seed
Seed uses the provided seed value to initialize the default Source to
a deterministic state. If Seed is not called, the generator behaves as
if seeded by Seed(1).
And you can see an example in the go cookbook:
rand.Seed(time.Now().Unix())
So wrapping up, you will have something like this:
package main
import(
"fmt"
"math/rand"
"time"
)
func add(x int, y int) int{
return x + y
}
func main() {
rand.Seed(time.Now().Unix())
var a int = rand.Intn(100)
var b int = rand.Intn(100)
fmt.Println(add(a, b))
}

Calculating large exponentiation in Golang

I've been trying to calculating 2^100 in Golang. I understand the limit of numeric type and tried using math/big package. Here's what I've tried but I can't figure out why it doesn't work.
I've used computation by powers of two method to calculate the exponentiation.
package main
import (
"fmt"
"math/big"
)
func main() {
two := big.NewInt(2)
hundred := big.NewInt(50)
fmt.Printf("2 ** 100 is %d\n", ExpByPowOfTwo(two, hundred))
}
func ExpByPowOfTwo(base, power *big.Int) *big.Int {
result := big.NewInt(1)
zero := big.NewInt(0)
for power != zero {
if modBy2(power) != zero {
multiply(result, base)
}
power = divideBy2(power)
base = multiply(base, base)
}
return result
}
func modBy2(x *big.Int) *big.Int {
return big.NewInt(0).Mod(x, big.NewInt(2))
}
func divideBy2(x *big.Int) *big.Int {
return big.NewInt(0).Div(x, big.NewInt(2))
}
func multiply(x, y *big.Int) *big.Int {
return big.NewInt(0).Mul(x, y)
}
BigInt package allows you to calculate x^y in log time (for some reason it is called exp). All you need is to pass nil as a last parameter.
package main
import (
"fmt"
"math/big"
)
func main() {
fmt.Println(new(big.Int).Exp(big.NewInt(5), big.NewInt(20), nil))
}
If you are interested how to calculate it by yourself, take a look at my implementation:
func powBig(a, n int) *big.Int{
tmp := big.NewInt(int64(a))
res := big.NewInt(1)
for n > 0 {
temp := new(big.Int)
if n % 2 == 1 {
temp.Mul(res, tmp)
res = temp
}
temp = new(big.Int)
temp.Mul(tmp, tmp)
tmp = temp
n /= 2
}
return res
}
or play with it on go playground.
For example,
package main
import (
"fmt"
"math/big"
)
func main() {
z := new(big.Int).Exp(big.NewInt(2), big.NewInt(100), nil)
fmt.Println(z)
}
Output:
1267650600228229401496703205376
Since it's a power of two, you could also do a bit shift:
package main
import (
"fmt"
"math/big"
)
func main() {
z := new(big.Int).Lsh(big.NewInt(1), 100)
fmt.Println(z)
}
Output:
1267650600228229401496703205376
You are returning immediately if power % 2 == 0. Instead, you just want to get the result of base ** (power /2). Then multiply result * result, and if power is even then multiply base to that.
To compute 2^100
package main
import (
"fmt"
"math/big"
)
func main() {
n := big.NewInt(0)
fmt.Println(n.SetBit(n, 100, 1))
}
Playground
package main
import(
"fmt"
"math/big"
)
func main() {
bigx, power10 := new(big.Int), new(big.Int)
var x int64
bigx.SetInt64(x) //set x int64 to bigx
power10.Exp(big.NewInt(10), bigx, nil) //power10 *big.Int points to solution
str10 := power10.Text(10)
fmt.Printf(str10) // print out the number and check for your self
}

Resources