0

I have a code:

package main

import ("fmt"
    "math/rand"
    "strconv"
)

func main() {
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
    fmt.Println(strconv.Itoa(rand.Int()))
}

When I run it (go run code.go), I get every time same values:

5577006791947779410
8674665223082153551
6129484611666145821
4037200794235010051
3916589616287113937
6334824724549167320
605394647632969758
1443635317331776148
894385949183117216
2775422040480279449
4751997750760398084
7504504064263669287
1976235410884491574
3510942875414458836

Second try:

package main

import ("fmt"
        "math/rand"
        "strconv"
)

func main() {
    fmt.Println(strconv.Itoa(rand.Intn(100)))
    fmt.Println(strconv.Itoa(rand.Intn(100)))
    fmt.Println(strconv.Itoa(rand.Intn(100)))
    fmt.Println(strconv.Itoa(rand.Intn(100)))
    fmt.Println(strconv.Itoa(rand.Intn(100)))
    fmt.Println(strconv.Itoa(rand.Intn(100)))
    fmt.Println(strconv.Itoa(rand.Intn(100)))
}

Same behaviour. Every time's

81
87
47
59
81
18
25

Is this a joke? Why it happens? Here is no description about non-random same result. I can see only pseudo-random term without explanation what that means.

Looks like even bash is more logical and stable...

This is a C way

random

rzlvmp
  • 7,512
  • 5
  • 16
  • 45
  • 4
    The description *is* in the doc you linked, it's just indirect. You might wonder and investigate about what "the default source" means – Hymns For Disco Jul 01 '21 at 04:24
  • 2
    There are two "types" of random number generators: Deterministic and Nondeterministic. The Nondeterministic is okay for cryptography and security but any other use of random numbers benefits if the experiment can be reproduced. No, this is not a joke, you just do not seem to understand the need for reproducable random numbers in math, physics, statistics, engineering and computer sience. – Volker Jul 01 '21 at 04:38
  • @Volker I don't understand why `Seed(1)` by default? Why not `Seed(2352)` or `Seed(0)`? Why most important thing hiding behind the scene? Why not `Seed(REAL_RANDOM_NUMBER)` by default at least? Why I must set `state` (`field`) directly to imports but not to new random `object` (`Struct`)? – rzlvmp Jul 01 '21 at 06:05
  • 1
    This is a pseudo random number generator and there is no difference between Seed(1) and Seed(2352) except that Seed(2352) is arbitrary and strange. And they idea of seeding with a "real random number" is a pretty awful one for several reasons: 1. Where do you want to take a "real random number" from? This is a hard problem and depends on what you consider "real random". – Volker Jul 01 '21 at 06:17
  • 2. Nobody wants its default PRNG to be non-deterministic. Non-determinism makes everything hard. Most people would need to construct their own RNG and seed it with 1 (or 2352) because the default one is non-deterministic. This would make your life a tiny bit simpler but the life of almost everybody else much worse. 3. PRNG behave like this since 30 years. Why change in the 31. year and break everybody's expectation about PRNGs? – Volker Jul 01 '21 at 06:21
  • @Volker I have write code in python, Java, javascript, php, bash and everywhere random is RANDOM by default. And only go has own specific way. When I import `"math/rand"` I don't want to use `"math/pseudorand"` – rzlvmp Jul 01 '21 at 06:31
  • 2
    That just shows that Python, Java and PHP got it wrong. In bash there is no need for determinstic randomness and that JavaScript got it wrong was to be expected. Contrast this with C, C++, FORTRAN and Lisp which got it right. – Volker Jul 01 '21 at 08:02
  • Ok, that is the reason. Now I see. I don't have experience with C-like languages so this behaviour was not natural for me. However, not sure which is `wrong` and which is `right` – rzlvmp Jul 01 '21 at 08:52
  • 1
    @rzlvmp pseudorandom number generators are what you get in every language. That's what general-purpose computers are capable of. True trandom number generators are complicated and require specialized hardware. Even the CSPRNG is still only pseudorandom, it just has an additional entropy source. See [random.org](https://www.random.org/randomness/) to learn more about randomness. – Adrian Jul 01 '21 at 13:28

3 Answers3

14

You need to seed it. It says right in the docs

Random numbers are generated by a Source. 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.

Generally

rand.Seed(time.Now().UnixNano())
dave
  • 62,300
  • 5
  • 72
  • 93
6

You don't appear to have called Seed for math/rand before using the generator.

If Seed is not called, the generator behaves as if seeded by Seed(1). That is not a joke - actually for a PRNG to be deterministic and repeatable is desirable in many cases.

For different numbers, seed with a different value, such as time.Now().UnixNano().

wim
  • 338,267
  • 99
  • 616
  • 750
0

Addition to the other answers, good explanation found about this in medium article go-how-are-random-numbers-generated

Go implements two packages to generate random numbers:

  • a pseudo-random number generator (PRNG) in the package math/rand cryptographic
  • pseudorandom number generator (CPRNG), implemented in crypto/rand

If both generate random numbers, your choice will be based on a tradeoff between genuinely random numbers and performance.

As other answers explain, math/rand packages populate random numbers reading from a source. So if you need random numbers, you need to set random seed calling rand.Seed()

In other case you can use crypto/rand package to generate random numbers. It generates random numbers which can not be deterministic. But performance is bit lower than math/rand package.

I have added sample code below for that. you can run and see different out put here.

package main

import (
    "crypto/rand"
    "math/big"
)

func main() {
    for i := 0; i < 4; i++  {
        n, _ := rand.Int(rand.Reader, big.NewInt(100))
        println(n.Int64())
    }
}
nipuna
  • 3,697
  • 11
  • 24
  • @airtonix You don't need to log in to see [This](https://medium.com/a-journey-with-go/go-how-are-random-numbers-generated-e58ee8696999) article. I can see it in incognito also. – nipuna Jul 11 '22 at 06:50
  • it's not consistent, I can't be bothered pressing more keys (but I'm sufficiently annoyed with this habit of medium and quora so i'll type essays in in cases like this...) so , next solution. – airtonix Jul 14 '22 at 03:40
  • @airtonix, It is a reference for further readers. The relevant text I copied and put as a quoted text in the answer. Btw, thank you for your feedback. – nipuna Jul 14 '22 at 11:07