From 6efb6dfac8c89173e0474bbcb86c373ccadde680 Mon Sep 17 00:00:00 2001 From: charlie <3140647@qq.com> Date: Thu, 31 Mar 2022 11:41:41 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9A=8F=E6=9C=BA=E6=95=B0=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rand/rand.go | 34 +++++++++++++++++------ rand/rand_test.go | 69 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 77 insertions(+), 26 deletions(-) diff --git a/rand/rand.go b/rand/rand.go index e079b12..5166b94 100644 --- a/rand/rand.go +++ b/rand/rand.go @@ -6,6 +6,7 @@ import ( "sync" "time" + "math/big" mrnd "math/rand" "github.com/charlienet/go-mixed/bytesconv" @@ -75,7 +76,7 @@ var ( ) // 生成指定长度的随机字符串 -func (scope *charScope) RandString(length int) string { +func (scope *charScope) Generate(length int) string { n := length if scope.lenFunc != nil { n = scope.lenFunc(n) @@ -99,15 +100,32 @@ func (scope *charScope) RandString(length int) string { return bytesconv.BytesToString(ret) } -// 获取指定范围内的随机数 -func RandInt(min, max int) int { - n := randNumber2(max - min) - return n + min +type scopeConstraint interface { + ~int | ~int32 | ~int64 } -// 生成指定范围的随机数 -func RandInt32(min, max int32) int32 { - return int32(RandInt(int(min), int(max))) +// 生成区间 n >= 0, n < max +func Intn[T scopeConstraint](max T) T { + n := mrnd.Int63n(int64(max)) + return T(n) % max +} + +// 生成区间 n >= min, n < max +func IntRange[T scopeConstraint](min, max T) T { + n := Intn(max - min) + return T(n + min) +} + +func CryptoRange[T scopeConstraint](min, max T) T { + n := CryptoIntn(max - min) + return min + n +} + +func CryptoIntn[T ~int | ~int32 | ~int64](max T) T { + b := big.NewInt(int64(max)) + n, _ := rand.Int(rand.Reader, b) + + return T(n.Int64()) } func RandBytes(len int) ([]byte, error) { diff --git a/rand/rand_test.go b/rand/rand_test.go index 91bd3d3..2e2a9fe 100644 --- a/rand/rand_test.go +++ b/rand/rand_test.go @@ -11,7 +11,7 @@ import ( ) func TestRandString(t *testing.T) { - t.Log(rand.AllChars.RandString(20)) + t.Log(rand.AllChars.Generate(20)) // b, err := rand.RandBytes(32) // t.Log(err) @@ -19,7 +19,7 @@ func TestRandString(t *testing.T) { } func TestRandHex(t *testing.T) { - h := rand.Hex.RandString(8) + h := rand.Hex.Generate(8) t.Log(h) } @@ -27,43 +27,61 @@ func TestRandMax(t *testing.T) { mrnd.Seed(time.Now().UnixNano()) } +func TestCryptRand(t *testing.T) { + t.Log(rand.CryptoIntn(56545)) +} + +func TestGenericsInterger(t *testing.T) { + var max int32 = 55 + + for i := 0; i < 1000; i++ { + if rand.Intn(max) >= max { + t.Fatal("生成的值大于最大值:", max) + } + } +} + +func TestRange(t *testing.T) { + min := 20 + max := 200000 + for i := 0; i < 100000000; i++ { + n := rand.IntRange(min, max) + if n < min { + t.Fatal("生成的值小于最小值:", min, n) + } + + if n >= max { + t.Fatal("生成的值大于最大值:", min, n) + } + } +} + func BenchmarkParallel(b *testing.B) { - rand.Hex.RandString(16) + rand.Hex.Generate(16) b.RunParallel(func(pb *testing.PB) { for pb.Next() { - rand.Hex.RandString(16) + rand.Hex.Generate(16) } }) } func BenchmarkNoop(b *testing.B) { for i := 0; i < b.N; i++ { - rand.AllChars.RandString(16) + rand.AllChars.Generate(16) } } func BenchmarkRandString(b *testing.B) { for i := 0; i < 10; i++ { - rand.Hex.RandString(10) + rand.Hex.Generate(10) } b.ResetTimer() for i := 0; i < b.N; i++ { - rand.Hex.RandString(20) + rand.Hex.Generate(20) } - - // b.Run("randString", func(b *testing.B) { - - // for i := 0; i < b.N; i++ { - // rand.Hex.RandString(256) - // } - // }) - - // for i := 0; i < b.N; i++ { - // rand.RandBytes(16) - // } } func BenchmarkString(b *testing.B) { @@ -116,3 +134,18 @@ func BenchmarkConcatString(b *testing.B) { } }) } + +func BenchmarkRand(b *testing.B) { + b.Run("math/rand", func(b *testing.B) { + for i := 0; i < b.N; i++ { + rand.Intn(100) + } + }) + + b.Run("crypto/rand", func(b *testing.B) { + for i := 0; i < b.N; i++ { + rand.CryptoIntn(100) + } + }) + +}