355 lines
6.1 KiB
Go
355 lines
6.1 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"math/rand"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
RAND32_M int32 = 2147483647
|
|
RAND32_A = 48271
|
|
RAND32_Q = RAND32_M / RAND32_A
|
|
RAND32_R = RAND32_M % RAND32_A
|
|
)
|
|
|
|
type RandomGenerator struct {
|
|
rand32_state int32
|
|
}
|
|
|
|
func (this *RandomGenerator) RandomSeed(seed int32) {
|
|
this.rand32_state = seed
|
|
}
|
|
|
|
func (this *RandomGenerator) Random() int32 {
|
|
hi := this.rand32_state / RAND32_Q
|
|
lo := this.rand32_state % RAND32_Q
|
|
test := RAND32_A*lo - RAND32_R*hi
|
|
if test > 0 {
|
|
this.rand32_state = test
|
|
} else {
|
|
this.rand32_state = test + RAND32_M
|
|
}
|
|
return this.rand32_state - 1
|
|
}
|
|
|
|
func (this *RandomGenerator) Rand32(max int32) int32 {
|
|
return this.Random() % max
|
|
}
|
|
|
|
func (this *RandomGenerator) GetRandomSeed() int32 {
|
|
return this.rand32_state
|
|
}
|
|
|
|
// [l..u)
|
|
func RandInt(args ...int) int {
|
|
switch len(args) {
|
|
case 0:
|
|
return rand.Int()
|
|
case 1:
|
|
if args[0] > 0 {
|
|
return rand.Intn(args[0])
|
|
} else {
|
|
return 0
|
|
}
|
|
default:
|
|
l := args[0]
|
|
u := args[1]
|
|
switch {
|
|
case l == u:
|
|
{
|
|
return l
|
|
}
|
|
case l > u:
|
|
{
|
|
return u + rand.Intn(l-u)
|
|
}
|
|
default:
|
|
{
|
|
return l + rand.Intn(u-l)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func RandItemByAvg(s1 []int64) int64 {
|
|
if len(s1)%2 != 0 {
|
|
return 0
|
|
}
|
|
rates := []int64{}
|
|
for i := 0; i < len(s1); i = i + 2 {
|
|
rates = append(rates, s1[i+1])
|
|
}
|
|
index := RandInt(0, len(rates))
|
|
return s1[index*2]
|
|
}
|
|
|
|
func RandItemByWight(s1 []int64) int64 {
|
|
if len(s1)%2 != 0 {
|
|
return 0
|
|
}
|
|
rates := []int64{}
|
|
for i := 0; i < len(s1); i = i + 2 {
|
|
rates = append(rates, s1[i+1])
|
|
}
|
|
index := RandSliceIndexByWight(rates)
|
|
return s1[index*2]
|
|
}
|
|
|
|
func RandSliceIndexByWight(s1 []int64) int {
|
|
total := int64(0)
|
|
for _, v := range s1 {
|
|
total += v
|
|
}
|
|
if total <= 0 {
|
|
return 0
|
|
}
|
|
random := rand.Int63n(total)
|
|
total = 0
|
|
for i, v := range s1 {
|
|
total += v
|
|
if random < total {
|
|
return i
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func RandSliceIndexByWight31N(s1 []int32) int {
|
|
total := int32(0)
|
|
for _, v := range s1 {
|
|
total += v
|
|
}
|
|
if total <= 0 {
|
|
return 0
|
|
}
|
|
random := rand.Int31n(total)
|
|
total = 0
|
|
for i, v := range s1 {
|
|
total += v
|
|
if random < total {
|
|
return i
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func RandSliceIndexByWightN(s1 []int) int {
|
|
total := 0
|
|
for _, v := range s1 {
|
|
total += v
|
|
}
|
|
if total <= 0 {
|
|
return 0
|
|
}
|
|
random := rand.Intn(total)
|
|
total = 0
|
|
for i, v := range s1 {
|
|
total += v
|
|
if random < total {
|
|
return i
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func RandNFromSlice(source []int, n int) []int {
|
|
if len(source) == 0 {
|
|
return source
|
|
}
|
|
if n > len(source) {
|
|
cycle := n / len(source)
|
|
rem := n % len(source)
|
|
for i := 0; i < cycle; i++ {
|
|
source = append(source, source...)
|
|
}
|
|
source = append(source, source[:rem]...)
|
|
}
|
|
idxs := rand.Perm(len(source))
|
|
ret := make([]int, len(source))
|
|
for i := 0; i < len(source); i++ {
|
|
ret[i] = source[idxs[i]]
|
|
}
|
|
return ret[:n]
|
|
}
|
|
func RandInt32Slice(source []int32) int32 {
|
|
if len(source) == 0 {
|
|
return 0
|
|
}
|
|
return source[rand.Intn(len(source))]
|
|
}
|
|
func RandFromRange(minValue, maxValue int32) int32 {
|
|
if minValue < 0 || maxValue < 0 {
|
|
return 0
|
|
}
|
|
if minValue >= maxValue {
|
|
return minValue
|
|
}
|
|
return rand.Int31n(maxValue-minValue+1) + minValue
|
|
}
|
|
|
|
func RandFromRangeInt64(minValue, maxValue int64) int64 {
|
|
if minValue < 0 || maxValue < 0 {
|
|
return 0
|
|
}
|
|
if minValue >= maxValue {
|
|
return minValue
|
|
}
|
|
return rand.Int63n(maxValue-minValue+1) + minValue
|
|
}
|
|
|
|
func RandSmsCode() string {
|
|
//seed := rand.Int()
|
|
//code := seed % 999999
|
|
//return strconv.Itoa(code)
|
|
return fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))
|
|
}
|
|
func RandSlice(n int) []int {
|
|
return rand.Perm(n)
|
|
}
|
|
func RandValueByRang(value int, l, u int) int {
|
|
r := RandInt(l, u)
|
|
return int(float64(value) * float64(r) / 100)
|
|
}
|
|
|
|
// 随机一个索引,最大的是 中间索引
|
|
func RandMaxMiddle(arrLen int) int {
|
|
if arrLen <= 0 {
|
|
return 0
|
|
}
|
|
if arrLen%2 == 0 {
|
|
return rand.Intn(arrLen / 2)
|
|
} else {
|
|
return rand.Intn(arrLen/2 + 1)
|
|
}
|
|
}
|
|
|
|
// 随机一个索引,最小的是 中间索引
|
|
func RandLastMiddle(arrLen int) int {
|
|
if arrLen <= 0 {
|
|
return 0
|
|
}
|
|
if arrLen%2 == 0 {
|
|
return rand.Intn(arrLen/2) + arrLen/2
|
|
} else {
|
|
return rand.Intn(arrLen/2+1) + arrLen/2
|
|
}
|
|
}
|
|
|
|
// 获得一个线性的随机概率是否满足
|
|
func RandLineInt64(curvalue, minValue, maxValue int64) bool {
|
|
ret := RandFromRangeInt64(minValue, maxValue)
|
|
if curvalue > ret {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// 获得一个正态分布的随机概率是否满足 cur max 都需要传入正值,用法不太对
|
|
func RandNormInt64(cur int64, max int64) bool {
|
|
t := math.Abs(rand.NormFloat64()) / 3
|
|
if t > 1 {
|
|
t = 1
|
|
}
|
|
if cur >= max {
|
|
return true
|
|
}
|
|
|
|
return cur > int64(t*float64(max))
|
|
}
|
|
|
|
// 获得最小公倍数
|
|
func GetMinCommonRate(array []int64) int64 {
|
|
ret := nlcm(array, len(array))
|
|
return ret
|
|
}
|
|
|
|
func gcd(a int64, b int64) int64 {
|
|
if a < b {
|
|
a, b = b, a
|
|
}
|
|
|
|
if b == 0 {
|
|
return a
|
|
} else {
|
|
return gcd(b, a%b)
|
|
}
|
|
}
|
|
|
|
func ngcd(array []int64, n int) int64 {
|
|
if n == 1 {
|
|
return array[0]
|
|
}
|
|
|
|
return gcd(array[n-1], ngcd(array, n-1))
|
|
}
|
|
|
|
func lcm(a int64, b int64) int64 {
|
|
return a * b / gcd(a, b)
|
|
}
|
|
|
|
func nlcm(array []int64, n int) int64 {
|
|
if n == 1 {
|
|
return array[0]
|
|
|
|
} else {
|
|
return lcm(array[n-1], nlcm(array, n-1))
|
|
}
|
|
}
|
|
|
|
// 随机生成遍历的数组列表
|
|
func GetRandomList(num int) []int {
|
|
var ret []int
|
|
for i := 0; i < num; i++ {
|
|
ret = append(ret, i)
|
|
r := RandInt(len(ret))
|
|
ret[i], ret[r] = ret[r], ret[i]
|
|
}
|
|
|
|
return ret
|
|
}
|
|
|
|
// 从A中随机出B个数字
|
|
func GetBNumFromA(A []int32, B int) []int32 {
|
|
if B >= len(A) {
|
|
return A
|
|
}
|
|
var ret []int32
|
|
|
|
var rate []int
|
|
for {
|
|
index := rand.Intn(len(A))
|
|
if !InSliceInt(rate, index) {
|
|
rate = append(rate, index)
|
|
ret = append(ret, A[index])
|
|
if len(ret) >= B {
|
|
return ret
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func GetBElementFromA(A []interface{}, B int) []interface{} {
|
|
if B >= len(A) {
|
|
return A
|
|
}
|
|
var ret []interface{}
|
|
|
|
var rate []int
|
|
for {
|
|
index := rand.Intn(len(A))
|
|
if !InSliceInt(rate, index) {
|
|
rate = append(rate, index)
|
|
ret = append(ret, A[index])
|
|
if len(ret) >= B {
|
|
return ret
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func RandFloat(min, max float64) float64 {
|
|
return min + rand.Float64()*(max-min)
|
|
}
|