480 lines
12 KiB
Plaintext
480 lines
12 KiB
Plaintext
|
|
package mathUtil
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"errors"
|
|||
|
|
"math/rand"
|
|||
|
|
"time"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
type Rand struct {
|
|||
|
|
*rand.Rand
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type weightRand struct {
|
|||
|
|
index int
|
|||
|
|
weight int
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获得Rand对象(如果是循环生成多个数据,则只需要调用本方法一次,而不能调用多次,否则会得到相同的随机值)
|
|||
|
|
func GetRand() *Rand {
|
|||
|
|
return &Rand{
|
|||
|
|
Rand: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func GetRandInSeed(seed int64) *Rand {
|
|||
|
|
return &Rand{
|
|||
|
|
Rand: rand.New(rand.NewSource(seed)),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取指定区间的随机数[lower, upper)
|
|||
|
|
// lower:区间下限
|
|||
|
|
// upper:区间上限
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandRangeInt(lower, upper int) int {
|
|||
|
|
return lower + this.Intn(upper-lower)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取指定区间的随机数[lower, upper)
|
|||
|
|
// lower:区间下限
|
|||
|
|
// upper:区间上限
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandRangeInt32(lower, upper int32) int32 {
|
|||
|
|
return lower + this.Int31n(upper-lower)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取指定区间的随机数[lower, upper)
|
|||
|
|
// lower:区间下限
|
|||
|
|
// upper:区间上限
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandRangeInt64(lower, upper int64) int64 {
|
|||
|
|
return lower + this.Int63n(upper-lower)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机数[0, n)
|
|||
|
|
// randObj:随机对象
|
|||
|
|
// n:范围上限
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandInt(n int) int {
|
|||
|
|
return this.Intn(n)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机数[0, n)
|
|||
|
|
// n:范围上限
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandInt32(n int32) int32 {
|
|||
|
|
return this.Int31n(n)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机数[0, n)
|
|||
|
|
// randObj:随机对象
|
|||
|
|
// n:范围上限
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandInt64(n int64) int64 {
|
|||
|
|
return this.Int63n(n)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机数[0, 1)
|
|||
|
|
// randObj:随机对象
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandFloat32() float32 {
|
|||
|
|
return this.Float32()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机数[0, 1)
|
|||
|
|
// 返回值:随机数
|
|||
|
|
func (this *Rand) GetRandFloat64() float64 {
|
|||
|
|
return this.Float64()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机数列表(取值范围:[minValue, maxValue],注意:maxValue-minValue < 10000,区间大小超过10000会抛出异常)
|
|||
|
|
// minValue:获取随机数的区间下限值
|
|||
|
|
// maxValue:获取随机数的区间上限值
|
|||
|
|
// count:随机数量
|
|||
|
|
// ifAllowDuplicate:是否允许重复
|
|||
|
|
// 返回值
|
|||
|
|
// 随机数列表
|
|||
|
|
func (this *Rand) GetRandNumList(minValue, maxValue, count int, ifAllowDuplicate bool) ([]int, error) {
|
|||
|
|
if minValue > maxValue {
|
|||
|
|
return nil, errors.New("minValue can't be bigger than maxValue.")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if !ifAllowDuplicate && (maxValue-minValue+1) < count {
|
|||
|
|
return nil, errors.New("随机的数量超过区间的元素数量")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (maxValue - minValue + 1) > 10000 {
|
|||
|
|
return nil, errors.New("随机数的区间不能大于10000")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定义原始数据
|
|||
|
|
sourceCount := maxValue - minValue + 1
|
|||
|
|
source := make([]int, sourceCount, sourceCount)
|
|||
|
|
for index := 0; index < sourceCount; index++ {
|
|||
|
|
source[index] = minValue + index
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定义返回值
|
|||
|
|
resultList := make([]int, 0, count)
|
|||
|
|
|
|||
|
|
// 获取随机的索引列表
|
|||
|
|
randIndextList := this.getRandIndexList(len(source), count, ifAllowDuplicate)
|
|||
|
|
for _, index := range randIndextList {
|
|||
|
|
// 判断是否已经取到足够数量的数据?
|
|||
|
|
if count <= 0 {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resultList = append(resultList, source[index])
|
|||
|
|
count -= 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return resultList, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机的int列表
|
|||
|
|
// source:源列表
|
|||
|
|
// count:随机数量
|
|||
|
|
// ifAllowDuplicate:是否允许重复
|
|||
|
|
// 返回值
|
|||
|
|
// 随机数列表
|
|||
|
|
func (this *Rand) GetRandIntList(source []int, count int, ifAllowDuplicate bool) ([]int, error) {
|
|||
|
|
// 在不允许重复的情况下,需要产生的随机数不能超过范围限制
|
|||
|
|
if ifAllowDuplicate == false && len(source) < count {
|
|||
|
|
return nil, errors.New("随机的数量超过列表的元素数量")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定义返回值
|
|||
|
|
resultList := make([]int, 0, count)
|
|||
|
|
|
|||
|
|
// 获取随机的索引列表
|
|||
|
|
randIndextList := this.getRandIndexList(len(source), count, ifAllowDuplicate)
|
|||
|
|
for _, index := range randIndextList {
|
|||
|
|
// 判断是否已经取到足够数量的数据?
|
|||
|
|
if count <= 0 {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resultList = append(resultList, source[index])
|
|||
|
|
count -= 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return resultList, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机的int32列表
|
|||
|
|
// source:源列表
|
|||
|
|
// count:随机数量
|
|||
|
|
// ifAllowDuplicate:是否允许重复
|
|||
|
|
// 返回值
|
|||
|
|
// 随机数列表
|
|||
|
|
func (this *Rand) GetRandInt32List(source []int32, count int, ifAllowDuplicate bool) ([]int32, error) {
|
|||
|
|
// 在不允许重复的情况下,需要产生的随机数不能超过范围限制
|
|||
|
|
if ifAllowDuplicate == false && len(source) < count {
|
|||
|
|
return nil, errors.New("随机的数量超过列表的元素数量")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定义返回值
|
|||
|
|
resultList := make([]int32, 0, count)
|
|||
|
|
|
|||
|
|
// 获取随机的索引列表
|
|||
|
|
randIndextList := this.getRandIndexList(len(source), count, ifAllowDuplicate)
|
|||
|
|
for _, index := range randIndextList {
|
|||
|
|
// 判断是否已经取到足够数量的数据?
|
|||
|
|
if count <= 0 {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resultList = append(resultList, source[index])
|
|||
|
|
count -= 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return resultList, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机的int64列表
|
|||
|
|
// source:源列表
|
|||
|
|
// count:随机数量
|
|||
|
|
// ifAllowDuplicate:是否允许重复
|
|||
|
|
// 返回值
|
|||
|
|
// 随机数列表
|
|||
|
|
func (this *Rand) GetRandInt64List(source []int64, count int, ifAllowDuplicate bool) ([]int64, error) {
|
|||
|
|
// 在不允许重复的情况下,需要产生的随机数不能超过范围限制
|
|||
|
|
if ifAllowDuplicate == false && len(source) < count {
|
|||
|
|
return nil, errors.New("随机的数量超过列表的元素数量")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定义返回值
|
|||
|
|
resultList := make([]int64, 0, count)
|
|||
|
|
|
|||
|
|
// 获取随机的索引列表
|
|||
|
|
randIndextList := this.getRandIndexList(len(source), count, ifAllowDuplicate)
|
|||
|
|
for _, index := range randIndextList {
|
|||
|
|
// 判断是否已经取到足够数量的数据?
|
|||
|
|
if count <= 0 {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resultList = append(resultList, source[index])
|
|||
|
|
count -= 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return resultList, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机的int64列表
|
|||
|
|
// source:源列表
|
|||
|
|
// count:随机数量
|
|||
|
|
// ifAllowDuplicate:是否允许重复
|
|||
|
|
// 返回值
|
|||
|
|
// 随机数列表
|
|||
|
|
func (this *Rand) GetRandStringList(source []string, count int, ifAllowDuplicate bool) ([]string, error) {
|
|||
|
|
// 在不允许重复的情况下,需要产生的随机数不能超过范围限制
|
|||
|
|
if ifAllowDuplicate == false && len(source) < count {
|
|||
|
|
return nil, errors.New("随机的数量超过列表的元素数量")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定义返回值
|
|||
|
|
resultList := make([]string, 0, count)
|
|||
|
|
|
|||
|
|
// 获取随机的索引列表
|
|||
|
|
randIndextList := this.getRandIndexList(len(source), count, ifAllowDuplicate)
|
|||
|
|
for _, index := range randIndextList {
|
|||
|
|
// 判断是否已经取到足够数量的数据?
|
|||
|
|
if count <= 0 {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resultList = append(resultList, source[index])
|
|||
|
|
count -= 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return resultList, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机的interface{}列表
|
|||
|
|
// source:源列表
|
|||
|
|
// count:随机数量
|
|||
|
|
// ifAllowDuplicate:是否允许重复
|
|||
|
|
// 返回值
|
|||
|
|
// 随机数列表
|
|||
|
|
func (this *Rand) GetRandInterfaceList(source []interface{}, count int, ifAllowDuplicate bool) ([]interface{}, error) {
|
|||
|
|
// 在不允许重复的情况下,需要产生的随机数不能超过范围限制
|
|||
|
|
if ifAllowDuplicate == false && len(source) < count {
|
|||
|
|
return nil, errors.New("随机的数量超过列表的元素数量")
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 定义返回值
|
|||
|
|
resultList := make([]interface{}, 0, count)
|
|||
|
|
|
|||
|
|
// 获取随机的索引列表
|
|||
|
|
randIndextList := this.getRandIndexList(len(source), count, ifAllowDuplicate)
|
|||
|
|
for _, index := range randIndextList {
|
|||
|
|
// 判断是否已经取到足够数量的数据?
|
|||
|
|
if count <= 0 {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
resultList = append(resultList, source[index])
|
|||
|
|
count -= 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return resultList, nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取随机的索引列表
|
|||
|
|
// count:数量
|
|||
|
|
// ifAllowDuplicate:是否允许重复
|
|||
|
|
// 返回值
|
|||
|
|
// 随机索引值列表
|
|||
|
|
func (this *Rand) getRandIndexList(maxNum, count int, ifAllowDuplicate bool) []int {
|
|||
|
|
// 定义返回值
|
|||
|
|
randIndextList := make([]int, 0, count)
|
|||
|
|
|
|||
|
|
// 使用源列表的数据量来初始化一个仅存放索引值的数组
|
|||
|
|
indexList := make([]int, maxNum, maxNum)
|
|||
|
|
for index := 0; index < maxNum; index++ {
|
|||
|
|
indexList[index] = index
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 遍历列表并获取随机对象(通过不断缩小随机的范围来实现)
|
|||
|
|
maxIndex := len(indexList) - 1
|
|||
|
|
for {
|
|||
|
|
if len(randIndextList) < count {
|
|||
|
|
// 获取随机索引(由于Next方法不取上限值,所以需要maxIndex+1)
|
|||
|
|
randIndex := this.Intn(maxIndex + 1)
|
|||
|
|
|
|||
|
|
// 将数据添加到列表,并增加findCount
|
|||
|
|
randIndextList = append(randIndextList, indexList[randIndex])
|
|||
|
|
|
|||
|
|
// 如果不允许重复,则需要特殊处理
|
|||
|
|
if !ifAllowDuplicate {
|
|||
|
|
// 将该位置的数据和最大位置的数据进行交换
|
|||
|
|
indexList[randIndex], indexList[maxIndex] = indexList[maxIndex], indexList[randIndex]
|
|||
|
|
|
|||
|
|
// 将随机的范围缩小
|
|||
|
|
maxIndex -= 1
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return randIndextList
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取带权重的随机数据
|
|||
|
|
// source:源数据
|
|||
|
|
// 返回值
|
|||
|
|
// 数据项
|
|||
|
|
// 错误对象
|
|||
|
|
func (this *Rand) GetRandWeight(source []IWeight) (result IWeight, err error) {
|
|||
|
|
if source == nil || len(source) == 0 {
|
|||
|
|
err = errors.New("待随机的列表为空")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 计算出总的数据量,并随机一个[0, total)的值
|
|||
|
|
total := 0
|
|||
|
|
for _, item := range source {
|
|||
|
|
total += item.GetWeight()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
randNum := this.GetRandInt(total)
|
|||
|
|
|
|||
|
|
// 根据随机出来的值,判断位于哪个区间
|
|||
|
|
total = 0
|
|||
|
|
for _, item := range source {
|
|||
|
|
total += item.GetWeight()
|
|||
|
|
if randNum < total {
|
|||
|
|
result = item
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
err = errors.New("未找到有效的数据")
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取带权重的随机数据
|
|||
|
|
// source:源数据
|
|||
|
|
// count:返回数量
|
|||
|
|
// ifAllowDuplicate:返回索引中是否允许包含重复项
|
|||
|
|
// 返回值
|
|||
|
|
// 数据项的索引
|
|||
|
|
// 错误对象
|
|||
|
|
func (this *Rand) GetRandItemsByWeight(source []IWeight, count int, ifAllowDuplicate bool) ([]int, error) {
|
|||
|
|
var err error
|
|||
|
|
if source == nil || len(source) == 0 {
|
|||
|
|
err = errors.New("待随机的列表为空")
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
if count <= 0 {
|
|||
|
|
err = errors.New("count 必须大于0")
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
var lenCount int = len(source)
|
|||
|
|
if lenCount < count && ifAllowDuplicate == false {
|
|||
|
|
err = errors.New("source长度小于count,并且设定为不可重复,请修复")
|
|||
|
|
return nil, err
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 准备数据
|
|||
|
|
total := 0
|
|||
|
|
weightList := make([]*weightRand, 0, lenCount)
|
|||
|
|
for i, item := range source {
|
|||
|
|
tempWeight := item.GetWeight()
|
|||
|
|
weightList = append(weightList, &weightRand{index: i, weight: tempWeight})
|
|||
|
|
total = total + tempWeight
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if lenCount <= count {
|
|||
|
|
return this.countLessThanRand(count, total, weightList), nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return this.countIsGreaterThanRand(count, total, weightList), nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取带权重的随机数据(列表元素数量<=需要的数量)
|
|||
|
|
// count:需要数量
|
|||
|
|
// total:总权重
|
|||
|
|
// weightList:权重列表
|
|||
|
|
// 返回值
|
|||
|
|
// 数据项的索引
|
|||
|
|
func (this *Rand) countLessThanRand(count, total int, weightList []*weightRand) []int {
|
|||
|
|
// 先所有的加入进去
|
|||
|
|
result := make([]int, 0, count)
|
|||
|
|
for k := range weightList {
|
|||
|
|
result = append(result, k)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 不删除随机
|
|||
|
|
tempCount := len(result)
|
|||
|
|
if tempCount >= count {
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for i := 0; i < count-tempCount; i++ {
|
|||
|
|
tempk := -1
|
|||
|
|
tempTotal := 0
|
|||
|
|
tempRandNum := this.GetRandInt(total + 1)
|
|||
|
|
for _, w := range weightList {
|
|||
|
|
tempTotal = tempTotal + w.weight
|
|||
|
|
if tempTotal > tempRandNum {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
tempk = w.index
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果未找到,则取第一个
|
|||
|
|
if tempk == -1 {
|
|||
|
|
tempk = weightList[0].index
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
result = append(result, tempk)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取带权重的随机数据(列表元素数量>需要的数量)
|
|||
|
|
// count:需要数量
|
|||
|
|
// total:总权重
|
|||
|
|
// weightList:权重列表
|
|||
|
|
// 返回值
|
|||
|
|
// 数据项的索引
|
|||
|
|
func (this *Rand) countIsGreaterThanRand(count, total int, weightList []*weightRand) []int {
|
|||
|
|
// 真随机+删除
|
|||
|
|
result := make([]int, 0, count)
|
|||
|
|
for j := 0; j < count; j++ {
|
|||
|
|
tempTotal := 0
|
|||
|
|
ri := -1
|
|||
|
|
var tw *weightRand
|
|||
|
|
tempRandNum := this.GetRandInt(total)
|
|||
|
|
for i, v := range weightList {
|
|||
|
|
tempTotal = tempTotal + v.weight
|
|||
|
|
if tempTotal > tempRandNum {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
tw = v
|
|||
|
|
ri = i
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果未找到,则取第一个
|
|||
|
|
if tw == nil {
|
|||
|
|
tw = weightList[0]
|
|||
|
|
ri = 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
result = append(result, tw.index)
|
|||
|
|
total = total - tw.weight
|
|||
|
|
|
|||
|
|
// 删除已经随机过的item
|
|||
|
|
weightList = append(weightList[:ri], weightList[ri+1:]...)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return result
|
|||
|
|
}
|