Files
bl/common/utils/random/random.go

144 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package random
import (
"math/rand"
"time"
)
// RandomXS128 实现 xorshift128+ 伪随机数生成器
type RandomXS128 struct {
seed0 uint64 // 内部状态前半部分
seed1 uint64 // 内部状态后半部分
}
// 归一化常数
const (
normDouble = 1.0 / (1 << 53)
normFloat = 1.0 / (1 << 24)
)
// NewRandomXS128 创建一个新的随机数生成器,自动生成初始种子
func NewRandomXS128() *RandomXS128 {
// 用系统随机数初始化种子(模拟 Java 中 new Random().nextLong() 的行为)
// 实际使用中可替换为更安全的种子源(如 crypto/rand
source := rand.NewSource(time.Now().UnixNano()) // 基于时间的种子源
r := rand.New(source) // 用种子源创建 Rand 实例
seed := uint64(r.Int())<<32 | uint64(r.Int())
return NewRandomXS128WithSeed(seed)
}
// NewRandomXS128WithSeed 用单个 uint64 种子创建生成器
func NewRandomXS128WithSeed(seed uint64) *RandomXS128 {
seed0 := murmurHash3(seed)
seed1 := murmurHash3(seed0)
return &RandomXS128{seed0: seed0, seed1: seed1}
}
// NewRandomXS128WithTwoSeeds 用两个 uint64 种子直接设置状态
func NewRandomXS128WithTwoSeeds(seed0, seed1 uint64) *RandomXS128 {
return &RandomXS128{seed0: seed0, seed1: seed1}
}
// NextLong 生成下一个 64 位随机整数
func (r *RandomXS128) NextLong() uint64 {
s1 := r.seed0
s0 := r.seed1
r.seed0 = s0
s1 ^= s1 << 23
r.seed1 = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26)
return r.seed1 + s0
}
// NextInt 生成下一个 32 位随机整数
func (r *RandomXS128) NextInt() int {
return int(r.NextLong() & 0xFFFFFFFF)
}
// NextIntN 生成 [0, n) 范围内的随机整数
func (r *RandomXS128) NextIntN(n int) int {
if n <= 0 {
panic("n must be positive")
}
for {
bits := int(r.NextLong() >> 1)
value := int(bits % n)
if bits-value+n-1 >= 0 {
return value
}
}
}
// NextLongN 生成 [0, n) 范围内的随机 64 位整数
func (r *RandomXS128) NextLongN(n uint64) uint64 {
if n <= 0 {
panic("n must be positive")
}
for {
bits := r.NextLong() >> 1
value := bits % n
if bits-value+(n-1) >= 0 {
return value
}
}
}
// NextDouble 生成 [0.0, 1.0) 范围内的随机浮点数
func (r *RandomXS128) NextDouble() float64 {
return float64(r.NextLong()>>11) * normDouble
}
// NextFloat 生成 [0.0, 1.0) 范围内的随机单精度浮点数
func (r *RandomXS128) NextFloat() float32 {
return float32(float64(r.NextLong()>>40) * normFloat)
}
// NextBoolean 生成随机布尔值
func (r *RandomXS128) NextBoolean() bool {
return (r.NextLong() & 1) != 0
}
// NextBytes 填充字节数组为随机字节
func (r *RandomXS128) NextBytes(b []byte) {
i := len(b)
for i > 0 {
n := i
if n > 8 {
n = 8
}
bits := r.NextLong()
for j := 0; j < n; j++ {
b[i-1-j] = byte(bits >> (8 * j))
}
i -= n
}
}
// SetSeed 用单个种子重置生成器状态
func (r *RandomXS128) SetSeed(seed uint64) {
seed0 := murmurHash3(seed)
r.seed0 = seed0
r.seed1 = murmurHash3(seed0)
}
// SetState 直接设置内部状态
func (r *RandomXS128) SetState(seed0, seed1 uint64) {
r.seed0 = seed0
r.seed1 = seed1
}
// GetState 获取内部状态
func (r *RandomXS128) GetState() (seed0, seed1 uint64) {
return r.seed0, r.seed1
}
// murmurHash3 用于种子扩展的哈希函数
func murmurHash3(x uint64) uint64 {
x ^= x >> 33
x *= 0xff51afd7ed558ccd
x ^= x >> 33
x *= 0xc4ceb9fe1a85ec53
x ^= x >> 33
return x
}