144 lines
3.4 KiB
Go
144 lines
3.4 KiB
Go
|
|
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
|
|||
|
|
}
|