golang随机整数和随机整数切片

1.随机整数

// GetRandomInt 随机获得一个在一定范围内的整数,范围[mi,mx)
func GetRandomInt(mi int, mx int) (int, error) {
    if mi >= mx {
        return 0, errors.New("输入的整数范围有误")
    }
    // 这里实时生成随机种子,而不用全局随机种子
    source := rand.NewSource(time.Now().UnixNano())
    rng := rand.New(source)
    randomInt := rng.Intn(mx-mi) + mi
    return randomInt, nil
}

2.随机整数切片

// GetUniqueRandomInts 随机获得在一定范围内的多个且唯一的整数,范围[mi,mx),结果是整数切片
func GetUniqueRandomInts(mi, mx, count int) ([]int, error) {
    if mi >= mx {
        return nil, errors.New("输入的整数范围有误")
    }
    if count > mx-mi {
        return nil, errors.New("要求的数量超限")
    }
    // 初始化包含指定范围所有整数的切片
    numbers := make([]int, mx-mi)
    for i := range numbers {
        numbers[i] = mi + i
    }
    // 打乱切片顺序
    source := rand.NewSource(time.Now().UnixNano())
    rng := rand.New(source)
    rng.Shuffle(len(numbers), func(i, j int) {
        numbers[i], numbers[j] = numbers[j], numbers[i]
    })
    // 截取所需数量的元素
    return numbers[:count], nil
}

3.拓展

  • 两个函数都使用了时间纳秒作随机种子,适用大部分场景,需要更高的安全性可以采用"seed, _ := rand.Int(rand.Reader, big.NewInt(1<<63-1))"生成更安全的种子.

4.对于随机整数切片的生成, 大模型给出的适用性更强的方案

func GetUniqueRandomInts(mi, mx, count int) ([]int, error) {
    // 参数校验
    if mi >= mx {
        return nil, fmt.Errorf("无效范围 [%d, %d)", mi, mx)
    }
    if count > mx-mi {
        return nil, fmt.Errorf("请求数量 %d 超过范围大小 %d", count, mx-mi)
    }

    // 小范围直接全量洗牌
    if mx-mi <= 1000 || count > (mx-mi)/2 {
        numbers := make([]int, mx-mi)
        for i := range numbers {
            numbers[i] = mi + i
        }

        seed, _ := rand.Int(rand.Reader, big.NewInt(1<<63-1))
        rng := rand.New(rand.NewSource(seed.Int64()))
        rng.Shuffle(len(numbers), func(i, j int) {
            numbers[i], numbers[j] = numbers[j], numbers[i]
        })
        return numbers[:count], nil
    }

    // 大范围使用蓄水池抽样
    result := make([]int, count)
    for i := 0; i < count; i++ {
        result[i] = mi + i
    }

    seed, _ := rand.Int(rand.Reader, big.NewInt(1<<63-1))
    rng := rand.New(rand.NewSource(seed.Int64()))
    for i := count; i < mx-mi; i++ {
        if j := rng.Intn(i + 1); j < count {
            result[j] = mi + i
        }
    }
    return result, nil
}

 

posted @ 2025-06-24 11:48  CJTARRR  阅读(38)  评论(0)    收藏  举报