Ce face math/rand/v2.New
Funcțiile de la nivelul pachetului (rand.IntN, rand.Float64…) folosesc un generator global inițializat aleatoriu, deci dau alte numere la fiecare rulare. Când ai nevoie de aceeași secvență de fiecare dată (teste, simulări pe care vrei să le repeți, un nivel de joc generat din același seed), îți creezi un generator propriu: r := rand.New(sursa). Obiectul *rand.Rand are aceleași metode: r.IntN, r.Float64, r.Perm, r.Shuffle etc.
Sursa dă biții aleatorii. rand.NewPCG(seed1, seed2) este rapidă și primește două numere uint64 ca seed. rand.NewChaCha8(seed) primește un seed de 32 de octeți și se bazează pe cifrul ChaCha8; este algoritmul folosit și de generatorul global. Pentru același seed, ambele dau mereu aceeași secvență, în orice versiune de Go.
rand.NewZipf(r, s, v, imax) creează un generator de valori între 0 și imax cu distribuție Zipf: valorile mici sunt foarte frecvente, cele mari rare, ca popularitatea paginilor unui site sau a cuvintelor dintr-un text. Probabilitatea lui k este proporțională cu (v + k)-s. Condițiile sunt s > 1 și v ≥ 1, altfel funcția returnează nil. Valorile le iei cu z.Uint64().
Parametri
| Parametru | Descriere |
|---|---|
src |
Pentru New: sursa de biți aleatorii (de exemplu rezultatul lui NewPCG sau NewChaCha8). |
seed1, seed2 |
Pentru NewPCG: cele două valori de pornire. |
seed |
Pentru NewChaCha8: valoarea de pornire, 32 de octeți. |
r, s, v, imax |
Pentru NewZipf: generatorul folosit, exponentul (> 1), decalajul (≥ 1) și valoarea maximă. |
Ce returnează
New: un *rand.Rand. NewPCG, NewChaCha8: o sursă (*rand.PCG, *rand.ChaCha8), care poate fi dată lui New. NewZipf: un *rand.Zipf sau nil dacă parametrii sunt invalizi.
Exemple
Exemplul 1: Același seed, aceeași secvență
Două generatoare create cu același seed dau exact aceleași numere. Un seed diferit dă altă secvență. Rezultatul este același la fiecare rulare.
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
a := rand.New(rand.NewPCG(2026, 1))
b := rand.New(rand.NewPCG(2026, 1))
c := rand.New(rand.NewPCG(2026, 2))
for range 3 {
fmt.Println(a.IntN(100), b.IntN(100), c.IntN(100))
}
}
Rezultat
46 46 16
20 20 76
87 87 3
Exemplul 2: Sursa ChaCha8 cu un seed de 32 de octeți
Seed-ul este un tablou [32]byte. Aici îl completăm dintr-un text; octeții rămași sunt 0.
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
var seed [32]byte
copy(seed[:], "dexblog.ro - exemplu")
r := rand.New(rand.NewChaCha8(seed))
elevi := []string{"Ana", "Mihai", "Ioana", "Radu", "Elena"}
r.Shuffle(len(elevi), func(i, j int) { elevi[i], elevi[j] = elevi[j], elevi[i] })
fmt.Println("Ordinea la oral:", elevi)
fmt.Printf("Zarul: %d, nota bonus: %.2f\n", r.IntN(6)+1, r.Float64())
}
Rezultat
Ordinea la oral: [Radu Elena Ana Ioana Mihai]
Zarul: 6, nota bonus: 0.67
Exemplul 3: Vizite simulate cu distribuția Zipf
Din 10000 de vizite simulate, prima pagină primește cele mai multe, iar numărul scade repede spre ultimele pagini. Ultimul rând arată că un exponent s ≤ 1 dă nil.
package main
import (
"fmt"
"math/rand/v2"
)
func main() {
pagini := []string{"acasă", "php", "python", "go", "rust", "despre"}
r := rand.New(rand.NewPCG(1, 2))
z := rand.NewZipf(r, 1.5, 1, uint64(len(pagini)-1))
vizite := make([]int, len(pagini))
for range 10000 {
vizite[z.Uint64()]++
}
for i, p := range pagini {
fmt.Printf("%-7s %5d\n", p, vizite[i])
}
fmt.Println(rand.NewZipf(r, 0.5, 1, 10) == nil)
}
Rezultat
acasă 5447
php 1968
python 1034
go 709
rust 467
despre 375
true
Greșeli frecvente
- Creezi generatorul cu un seed luat din timp (
time.Now().UnixNano()) ca să fie „mai aleatoriu”: nu este nevoie, funcțiile de la nivelul pachetului sunt deja inițializate aleatoriu. Generatorul propriu are sens când vrei un seed fix. - Folosești același
*rand.Randdin mai multe goroutine fără sincronizare: spre deosebire de funcțiile de la nivelul pachetului, un generator propriu nu este sigur pentru folosire concurentă. - Dai lui
NewZipfuns ≤ 1sauv < 1: primeștinil, iar apelulz.Uint64()oprește programul cupanic. - Folosești
NewChaCha8cu un seed fix pentru chei sau parole: cu seed cunoscut, secvența poate fi reprodusă de oricine. Pentru secrete foloseștecrypto/rand.
Comenzi înrudite
math/rand/v2.IntN: Returnează un număr întreg aleatoriu din intervalul [0, n): IntN pentru int, plus variantele Int32N, Int64N, UintN, Uint32N, Uint64N.math/rand/v2.Shuffle: Amestecă aleatoriu n elemente, apelând funcția swap pentru a interschimba elementele i și j.math/rand/v2.Float64: Returnează un număr zecimal aleatoriu uniform din intervalul [0.0, 1.0): Float64 sau Float32.math/rand/v2.Perm: Returnează o permutare aleatorie a numerelor 0, 1, …, n-1, ca slice nou de int.