用Java Random获取到2021(趣味向)

简介: 只需要0xffff、1、0、10这4个数字,就能通过Java Random获取到2021,也许没什么实际用处,但十分有趣

Random这个东西非常好玩,Random的seed使用的就是AtomicLong类型,AtomicLong的value使用的volatile关键字可以避免读取出寄存器中的脏数据,而数值更新时使用的Unsafe内存操作极其高效,完美的避免了synchronized的性能负担,这在Random.next()运作时非常重要,因为如果两次使用了同样的seed,在next()得到的随机结果必然相同。

好玩的地方在于,这个seed是可以设置的,不但在construction中可以自定义seed,也可以使用setSeed(long seed)切换到新的seed,这一点是很好理解的,毕竟将System.nanoTime()和一些魔法数字混合属于伪随机,Random将seed作为只写属性,为Random的真随机留了一扇门。

如果想生成一些奇怪的数字,random是再合适不过的了,只要有合适的seed与一个合适的bound,它几乎能得到任何范围内的值,我决定将bound设为10000,检索0到0xffff间的seed。

for (int i = 0; i < 0xffff; i++) {
   
    Random r = new Random(i);
    if (r.nextInt(10000) == 2021) {
   
        System.out.println(i);
    }
}
3318
14001
24132
25562
30727
46376
50878

由于范围小几乎秒出结果,这些seed都是合适的

使用不同的bound也可以得出合适的结果

for (int i = 0; i < 0xffff; i++) {
   
    Random r = new Random(1);
    if (r.nextInt(10000 + i) == 2021) {
   
        System.out.println(i);
    }
}
6286
22572
38187

以下两种方式都能得到2021

new Random(3318).nextInt(10000)
new Random(1).nextInt(16286)

不断的进行nextInt()可以得到更多数字,将seed置为0,round设在10000,经过不断nextInt()依然可以得到2021

Random r = new Random(1);
for (int i = 0; i < 15683; i++) {
   
    r.nextInt();
}
System.out.println(r.nextInt(10000));
//2021

注意: round不影响下一次随机时的seed。seed每次自动更新,都是由旧seed进行以下计算得出的

((oldseed * 0x5DEECE66DL + 0xBL) & 0xffffffffffff

现有的这些数字,都是一些杂乱数据,不美观,我扩大范围,将seed设为0xffff,由于0xffff这个范围对于2021还是太大,难以检索出有趣的数字,我右移一位,使round为实际值为0x7fff,进行海量的检索,找到了两个看上去很好玩的数字

42174
47124

看到这个突然眼前一亮,这两个数字互相倒置,循环数量达到这两个数字都会得到2021,我直接检索这种规则的数字,看看除了2021还有哪些

final int seed = 0xffff;
final int round = seed >> 1;
for (int i = 0; i < seed; i++) {
    
    Random foo = new Random(seed);
    Random bar = new Random(seed);
    int reverse = 0;
    int temp = i;
    while (temp != 0) {
    
        reverse = reverse * 10 + (temp % 10);
        temp /= 10;
    }
    //i % 10 == 0用来排除个位数的情况
    if (i == reverse || i % 10 == 0) {
    
        continue;
    }
    IntStream.range(0, i).forEach(e -> foo.nextInt());
    IntStream.range(0, reverse).forEach(e -> bar.nextInt());
    int res = foo.nextInt(round);
    if (res == bar.nextInt(round)) {
    
        System.out.println(res);
    }
}
}
18482
18482
2021
2021
16307

满足这种规则的数字确实稀少,除了2021还有18482,16307这两个数字,但2021恰好夹在中间好尴尬,不过这个16307为什么没有重复两次呢?我的规则是他的循环的次数,倒置过来也必须得到他呀,不应该有两次么,得看看他的循环次数,将打印行改为

System.out.println(res + ":" + i + ":" + reverse);

得到

18482:17092:29071
18482:29071:17092
2021:42174:47124
2021:47124:42174
16307:53609:90635

原来是因为将他的数字倒转,就超过了我设置的循环上限0xffff,他只能打印循环53609次的16307,无法进行90635的第二次打印,我加上reverse > n的判断排除它即可,现在就只需要倒排序,将2021放在首位,即可得到2021了

最终代码如下:

final int seed = 0xffff;
final int round = seed >> 1;
for (int i = seed; i > 0; i--) {
   
    Random foo = new Random(seed);
    Random bar = new Random(seed);
    int reverse = 0;
    int temp = i;
    while(temp != 0) {
   
        reverse = reverse * 10 + (temp % 10);
        temp /= 10;
    }
    if (i == reverse || i % 10 == 0 || reverse > seed) {
   
        continue;
    }
    IntStream.range(0, i).forEach(e -> foo.nextInt());
    IntStream.range(0, reverse).forEach(e -> bar.nextInt());
    int res = foo.nextInt(round);
    if (res == bar.nextInt(round)) {
   
        System.out.println(res);
        break;
    }
}

我同样贴在了 https://gist.github.com/lyrieek/61b435d26c10aba82b17d65f180199ab

目录
相关文章
|
1月前
|
Java
java的Random类和Arrays.sort类使用实例
java的Random类和Arrays.sort类使用实例
10 0
|
1月前
|
Java
java值random类的使用
java值random类的使用
10 0
|
1月前
|
Java
java的Math类和random类
java的Math类和random类
13 0
|
3月前
|
Java
Java系类 之 生成随机数(random()和Random类)
这篇文章介绍了Java中生成随机数的两种方法:使用`Math.random()`方法和`Random`类的实例方法,并提供了示例代码展示如何使用这些方法生成特定范围或特定条件下的随机数。
|
5月前
|
算法 Java 测试技术
滚雪球学Java(55):想让你的程序更有趣?加上这个Java的Random类的小技巧!
【6月更文挑战第9天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
41 2
滚雪球学Java(55):想让你的程序更有趣?加上这个Java的Random类的小技巧!
|
6月前
|
Java C语言
JAVA 初识 (一)JOptionPane、Scanner和Random的小认知
JAVA 初识 (一)JOptionPane、Scanner和Random的小认知
|
6月前
|
Java
Java——Math、BigInteger和Random类
Java——Math、BigInteger和Random类
44 0
|
6月前
|
存储 Java
35、Java 中的 Math 类、Random 随机数、UUID、格式化字符串或数字、字符串和数字的相互转换、高精度计算、BigDecimal、计算机中的浮点数都是近似值
35、Java 中的 Math 类、Random 随机数、UUID、格式化字符串或数字、字符串和数字的相互转换、高精度计算、BigDecimal、计算机中的浮点数都是近似值
95 0
|
安全 Java 数据安全/隐私保护
java random随机数的用法
java random随机数的用法
|
11月前
|
Java
【零基础学Java】—Random的基本概述和使用(十二)
【零基础学Java】—Random的基本概述和使用(十二)