随机生成Long全范围数

本文介绍了一种方法,通过十进制位分区和随机排序,实现生成Long型的全范围随机数。与内置Random.nextLong()函数相比,虽然自定义方法耗时较长,但能生成更广泛的数值范围。作者还提供了生成100个数的案例和时间性能对比数据。

前言

使用自带的Random.nextLong()函数生成Long型的长整数,范围比较小,如下图。100个随机数没看见10以内的数字。所以考虑实现随机化生成大范围的长整数。
随机生产100个长整数

实现思路

以十进制位按区间随机生产

  1. Long型最大和最小数为19位,所以考虑分成38个区间,例如[0,9],[-9,-1],[10,99]…

  2. 然而,Math.random生成[0,1)之间的小数,意味着取不到区间的右端点。故增加一个区间存放每个区间的右端点的索引。

  3. 最后的区间划分为38个十进制位区间和一个特殊区间,如此就能保证可取长整数范围内的所有数。

主要代码

分区

首先划分出38个十进制位的区间,最后处理特殊区间即可

private static long[][] groupLongRange() {
    int unitCnt = 19;
    int len = unitCnt * 2 + 1;
    long[][] range = new long[len][2];
    long p = 1;
    for (int i = 0; i < unitCnt; ++i) {
        long l,r;
        long nl, nr;
        nr = -1 * p;
        if (i == 0) {
            l = 0;
            r = p * 10 - 1;
            nl = -1 * p * 10 + 1;
        } else if (i == 18) {
            l = p;
            r = Long.MAX_VALUE;
            nl = Long.MIN_VALUE;
        } else {
            l = p;
            r = p * 10 - 1;
            nl = -1 * p * 10 + 1;
        }
        range[i][0] = l; range[i][1] = r;
        range[i + unitCnt][0] = nl; range[i + unitCnt][1] = nr;
        p *= 10;
    }
    // 存储区间的末尾数字
    range[len - 1][0] = 0;
    range[len - 1][1] = len - 1;
    return range;
}

为了尽可能随机化,将生产的每个区间随机化排序,注意最后一个区间不参与排序。

/**
 * left - 排序的左起端点
 * len - 排序的子数组长度
 */
private static void randomSort(long[][] arr, int left, int len) {
    long start = System.currentTimeMillis();
    boolean[] v = new boolean[len];
    int cnt = left;
    while (cnt < len) {
        int k = (int) (left + Math.random() * len);
        if (!v[k]) {
            swap(arr, cnt, k);
            v[k] = true;
            ++cnt;
        }
    }
}

private static void swap(long[][] arr, int i, int j) {
    long t1 = arr[i][0];
    long t2 = arr[i][1];
    arr[i][0] = arr[j][0];
    arr[i][1] = arr[j][1];
    arr[j][0] = t1;
    arr[j][1] = t2;
}

随机生成过程

先随机生产数组下标,再随机生成对应下标范围内的数,二次随机。如果第一次随机到最后一个区间时,取得是右端点值。主要过程如下:

int len = range.length;
int ri = (int) (Math.random() * len);
long num = range[ri][0] + (long) (Math.random() * (range[ri][1] - range[ri][0]));
if (ri == len - 1) {
    // 因为每个区间的末尾取不到,所以设计多一个空间来存储,每个区间的末尾的下标
    num = range[(int) num][1];
}
// num 就是随机生成的长整数

案例:随机生成100个数

在这里插入图片描述
可见范围比自带随机化的要广

朴素的比较

以下是从时间维度进行对比

比较项自定义随机化内置随机化
1000007ms2ms
10000000152ms77ms
100000000014409ms7388ms

总结

自定义随机化过程耗时长,但是生成的随机数范围广

在给定范围随机生成有多种方法,以下为不同场景下的实现方式: ### 生成指定日期范围内的随机日期 可使用 Java 语言,借助 `new Date(date)` 方法得到随机对应的时间。以下是代码示例: ```java import java.text.SimpleDateFormat; import java.util.Date; public class RandomDateGenerator { public static Date getRandomDate(String beginDate, String endDate) { try { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date start = format.parse(beginDate); Date end = format.parse(endDate); if (start.getTime() >= end.getTime()) { return null; } long date = (long) (Math.random() * (end.getTime() - start.getTime() + 1) + start.getTime()); return new Date(date); } catch (Exception e) { e.printStackTrace(); } return null; } } ``` 该方法传入开始日期和结束日期的字符串,返回此日期范围内的随机日期。若开始日期晚于或等于结束日期,则返回 `null` [^1]。 ### 在给定范围生成指定量且和固定的随机 使用 Python 语言实现,以下是示例代码: ```python import random def get_range(s, xrange, yrange): if (s < xrange[0] + yrange[0]) or (s > xrange[1] + yrange[1]): return [] res = [] for i in range(2): if yrange[0] <= s - xrange[i] <= yrange[1]: res.append(s - xrange[i]) if xrange[0] <= s - yrange[i] <= xrange[1]: res.append(yrange[i]) res.sort() return res def dec(s, n, mi, ma): if (s < n * mi) or (s > n * ma): return [] res = [] for i in range(n - 1): rand_range = get_range(s, [mi, ma], [mi * (n - i - 1), ma * (n - i - 1)]) r = random.uniform(rand_range[0], rand_range[1]) res.append(s - r) print(f'{s} = {r} + {s - r}') s = r res.append(s) return res if __name__ == '__main__': ans = dec(20, 10, 1.5, 2.1) for j in ans: print(j) ``` 上述代码中,`dec` 函可将一个 `s` 分解为 `n` 个范围在 `[mi, ma]` 内的随机,且这些随机之和为 `s` [^2]。 ### 多个字符中选取特定量的字符组成新字符串 使用 Python 语言,结合 `random.sample()` 函实现,示例代码如下: ```python import random import string result = ''.join(random.sample(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], 3)) print(result) ``` 此代码从给定的字符列表中随机选取 3 个字符,组合成新的字符串 [^3]。 ### 生成随机 在 Python 中,可使用 `randint()` 函,它是 `rand()` 函的特殊版本。`randint()` 能直接生成指定区间的随机,而 `rand()` 函需手动进行取整和区间变换操作。示例代码如下: ```python import random # 使用 randint() 函 random_int = random.randint(1, 10) print(random_int) ``` 上述代码会生成 1 到 10 之间(包含 1 和 10)的随机 [^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值