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
|
||
}
|