Java中的弱伪随机数Random 2020-05-12 11:33 随机数: Java中生成随机数有三个影响因素:**随机种子seed**,**随机范围bound** 和**产生随机数的对象Random**。 随机范围bound不同,生成的随机数肯定会有不同的可能,所以这里不做讨论。 下面讨论的是seed和随机对象Random对生成随机数的影响。生成随机数的对象又分为弱伪随机数和强伪随机数,我们这里讨论弱伪随机数。 ### 实验一:弱伪随机数生成规律 ```java /** * 弱伪随机数:相同的seed随机出来的数是一摸一样的,不同的seed随机数来的数字不同(这是对于不同的Random产生的随机数来说的,如果是同一个Random产生的,就不一定相同与否) * @param args * java.security.SecureRandom是强伪随机数 * java.util.Random 是弱伪随机数 */ public static void main(String[] args) { //--------------------------------------------Random1---------------------------------------------------------------- System.out.println("--------------------------------------------Random1:seed=100,不同Random对象,随机结果相同----------------------------------------------------------------"); ArrayList<Object> list1 = new ArrayList<>(100); ArrayList<Object> list2 = new ArrayList<>(100); //固定随机种子seed 这里两个都是以100作为seed Random t = new Random(100); Random t2 = new Random(100); //但是使用了不同Random对象生成随机数 for (int i = 0; i < 55; i++) { list1.add(t.nextInt(100));//bound限制产生100以内的随机数 } for (int i = 0; i < 55; i++) { list2.add(t2.nextInt(100)); } //所以结果会相同 System.out.println(list1); System.out.println(list2); //结论:(随机范围bound相同的情况下)使用不同Random对象,且使用相同的seed时,产生的随机结果会完全一致。由此可知随机数生成是一条线,每次重新起一个对象使用相同的seed生成随机数时,完全是走的相同的路,可理解伪固定的函数,参数相同,再调用一遍结果也相同。 //--------------------------------------------Random2---------------------------------------------------------------- System.out.println("--------------------------------------------Random2:seed=100,相同Random对象,随机结果不同----------------------------------------------------------------"); ArrayList<Object> list3 = new ArrayList<>(100); ArrayList<Object> list4 = new ArrayList<>(100); //固定随机种子seed Random t3 = new Random(100); //且使用相同Random对象生成随机数 for (int i = 0; i < 55; i++) { list3.add(t.nextInt(100)); } for (int i = 0; i < 55; i++) { list4.add(t.nextInt(100)); } //随机结果不同 System.out.println(list3); System.out.println(list4); //结论:由于使用同一个Random随机对象,所以相当于一条线一直往后走,随机结果不会完全重复(是否重复是看此随机函数本身产生的结果是否会重复,即不受外界影响)。 //--------------------------------------------Random3---------------------------------------------------------------- System.out.println("--------------------------------------------Random3:时钟作为seed,相同Random对象,随机结果不同。因为相同Random随机结果本就不同----------------------------------------------------------------"); ArrayList<Object> list5 = new ArrayList<>(100); ArrayList<Object> list6 = new ArrayList<>(100); //这里不写就是以时钟作为seed Random t5 = new Random(); for (int i = 0; i < 55; i++) { list5.add(t5.nextInt(100)); } for (int i = 0; i < 55; i++) { list6.add(t5.nextInt(100)); } //随机结果不同 System.out.println(list5); System.out.println(list6); //结论:和Random2一样,只要是使用同一个随机对象的,都是一条线往后走,但不能保证一定不会出现重复数据。 //--------------------------------------------Random4---------------------------------------------------------------- System.out.println("--------------------------------------------Random4:时钟作为seed,不同Random对象,随机结果不同。因为不同Random,他的随机种子seed是随着时间变化的,两行代码不是同一时间运行的,所以他们的seed值不同----------------------------------------------------------------"); ArrayList<Object> list7 = new ArrayList<>(100); ArrayList<Object> list8 = new ArrayList<>(100); //这里不写就是以时钟作为seed Random t7 = new Random(); Random t8 = new Random(); for (int i = 0; i < 55; i++) { list7.add(t7.nextInt(100)); } for (int i = 0; i < 55; i++) { list8.add(t8.nextInt(100)); } //随机结果不同 System.out.println(list7); System.out.println(list8); //结论:因为是使用时钟作为seed,在执行两个代码的时候时间是不同的,所以相当于seed不同 //--------------------------------------------org.apache.commons.lang3.RandomUtils---------------------------------------------------------------- //org.apache.commons.lang3.RandomUtils的随机实现也是弱伪随机数,因其内部是直接 private static final Random RANDOM = new Random(); 即使用时钟作为seed System.out.println("--------------------------------------------org.apache.commons.lang3.RandomUtils,永远不同。因为这个工具是静态的,每次调用内部使用的是同一个Random,跟上面的Random3一样----------------------------------------------------------------"); ArrayList<Object> lista = new ArrayList<>(100); ArrayList<Object> listb = new ArrayList<>(100); for (int i = 0; i < 55; i++) { lista.add(org.apache.commons.lang3.RandomUtils.nextInt()); //return nextInt(0, Integer.MAX_VALUE); 随机范围bound是Integer.MAX_VALUE } for (int i = 0; i < 55; i++) { listb.add(org.apache.commons.lang3.RandomUtils.nextInt()); } System.out.println(lista); System.out.println(listb); } ``` 结果: ```java --------------------------------------------Random:seek=100,不同Random,随机结果相同---------------------------------------------------------------- [15, 50, 74, 88, 91, 66, 36, 88, 23, 13, 22, 17, 56, 57, 52, 59, 80, 78, 73, 19, 53, 28, 65, 72, 67, 31, 48, 92, 0, 28, 74, 95, 16, 73, 44, 94, 87, 68, 6, 29, 55, 0, 39, 71, 31, 2, 85, 15, 62, 0, 58, 36, 19, 8, 59] [15, 50, 74, 88, 91, 66, 36, 88, 23, 13, 22, 17, 56, 57, 52, 59, 80, 78, 73, 19, 53, 28, 65, 72, 67, 31, 48, 92, 0, 28, 74, 95, 16, 73, 44, 94, 87, 68, 6, 29, 55, 0, 39, 71, 31, 2, 85, 15, 62, 0, 58, 36, 19, 8, 59] --------------------------------------------Random:seek=100,相同Random,随机结果不同---------------------------------------------------------------- [45, 25, 52, 45, 48, 46, 57, 22, 54, 88, 34, 53, 77, 11, 71, 30, 56, 0, 51, 24, 63, 92, 32, 87, 83, 46, 26, 98, 93, 34, 71, 94, 12, 33, 38, 26, 28, 90, 53, 79, 39, 59, 26, 55, 52, 10, 91, 21, 59, 57, 62, 68, 16, 84, 24] [4, 78, 10, 0, 8, 12, 34, 97, 86, 84, 39, 57, 45, 88, 52, 38, 69, 43, 30, 0, 8, 16, 49, 16, 35, 5, 41, 55, 83, 51, 38, 66, 98, 38, 99, 11, 97, 97, 92, 62, 59, 21, 55, 78, 9, 55, 53, 67, 90, 76, 43, 48, 79, 0, 11] --------------------------------------------Random:时钟作为seek,相同Random,随即结果不同。因为相同Random随机结果本就不同---------------------------------------------------------------- [37, 1, 43, 94, 43, 0, 56, 97, 38, 33, 15, 71, 97, 12, 38, 18, 70, 64, 23, 90, 48, 80, 33, 21, 77, 88, 59, 52, 22, 15, 71, 29, 71, 67, 96, 69, 43, 37, 41, 25, 95, 12, 57, 80, 43, 93, 3, 80, 9, 81, 46, 91, 83, 99, 15] [48, 91, 14, 58, 59, 65, 78, 4, 84, 68, 62, 66, 64, 32, 8, 0, 97, 6, 44, 98, 58, 16, 65, 73, 68, 29, 13, 67, 60, 5, 1, 40, 49, 95, 35, 85, 87, 52, 27, 26, 90, 30, 14, 99, 1, 21, 97, 14, 82, 49, 83, 57, 74, 13, 45] --------------------------------------------Random:时钟作为seek,不同Random,随即结果不同。因为不同Random,他的随机种子seek是随着时间变化的,两行代码不是同一时间运行的,所以他们的seek值不同---------------------------------------------------------------- [78, 23, 89, 52, 94, 23, 66, 52, 11, 55, 62, 16, 30, 89, 79, 95, 26, 90, 77, 2, 20, 37, 50, 55, 19, 43, 86, 19, 42, 30, 32, 53, 77, 79, 68, 26, 92, 97, 65, 85, 3, 40, 43, 89, 9, 50, 61, 53, 57, 33, 84, 52, 30, 6, 96] [96, 38, 80, 78, 64, 2, 10, 70, 95, 98, 81, 56, 89, 69, 41, 87, 30, 84, 59, 51, 4, 2, 55, 61, 14, 97, 1, 12, 58, 51, 33, 29, 95, 21, 79, 76, 98, 74, 66, 50, 27, 9, 76, 11, 69, 12, 87, 57, 6, 41, 63, 56, 48, 7, 61] --------------------------------------------org.apache.commons.lang3.RandomUtils,永远不同。因为这个工具是静态的,每次调用内部使用的是同一个Random,跟上面的Random3一样---------------------------------------------------------------- [1893665739, 257930553, 135278889, 830196142, 462095529, 1538972871, 131015981, 876091756, 348454191, 45715846, 1590689601, 1797587540, 65849987, 2128440538, 959475095, 1134108238, 1363057003, 1412258418, 1557545138, 1109175529, 599770516, 464633544, 1404869820, 1788244652, 144022399, 1700086728, 836544135, 1379793803, 1542852361, 496668040, 46777886, 552751733, 446238869, 2082027830, 373373191, 1093885962, 34720471, 423143440, 1961774617, 510476906, 1499575104, 54868107, 320881908, 1940394025, 1846277889, 618966935, 1271163680, 1042520158, 2072932030, 188265466, 1917235397, 118346203, 1410196177, 483024345, 1604620036] [1450953590, 601229880, 1103625302, 1101117938, 590876550, 44715548, 1112429394, 944486447, 1811319914, 1416297471, 42513235, 1165040166, 2116891715, 652423297, 310865281, 1694673635, 1045538241, 391013582, 786580939, 2015401099, 2007978011, 870918311, 2142545191, 1014698621, 1284416536, 1263481612, 794521078, 1313729284, 18678859, 2099352452, 1840804997, 2117569205, 227427932, 1611820552, 1438498224, 1629502316, 426489728, 1973439378, 1774372257, 1425248477, 1074902538, 1512155453, 1372074166, 1622525145, 2082214427, 1625427993, 292710529, 1394629920, 1578272629, 983342989, 139052776, 1141707997, 1026146926, 221549673, 2111246701] Process finished with exit code 0 ``` ### 实验二:生成的随机数全不同吗 > 只是随机数,因为是随机的,所以不能保证产生的数字完全不同,但是这个出现重复的原因是随机算法导致的,不是人为干扰或者使用错误导致的。即随机数本来就是有可能重复的。 ```java /** * 同一个Random生产的随机数一定是不同的吗? 不是 * @param args */ public static void main(String[] args) { HashSet<Object> set = new HashSet<>(); Random random = new Random(); for (int i = 0; i < 1000; i++) { set.add(random.nextInt(100)); } System.out.println(set.size()); // 100 //生成1000个随机数,但是结果只有100个不同的,其他都是重复的 HashSet<Object> set2 = new HashSet<>(); Random random2 = new Random(); for (int i = 0; i < 10000; i++) { set2.add(random2.nextInt(10000)); } System.out.println(set2.size()); // 6284 //生成10000个随机数,即使bound取值为10000,也不能保证所生成的随机数全部不同 HashSet<Object> set3 = new HashSet<>(); Random random3 = new Random(); for (int i = 0; i < 10000; i++) { set3.add(random3.nextInt(100000)); } System.out.println(set3.size()); // 9513 //即使扩大bound的范围 } ``` ### 实验三:强伪随机数 ```java public static void main(String[] args) { SecureRandom secureRandom3 = new SecureRandom("".getBytes()); SecureRandom secureRandom4 = new SecureRandom("".getBytes()); ArrayList<Object> list3 = new ArrayList<>(); for (int i = 0; i < 100; i++) { list3.add(secureRandom3.nextInt(100)); } ArrayList<Object> list4 = new ArrayList<>(); for (int i = 0; i < 100; i++) { list4.add(secureRandom4.nextInt(100)); } System.out.println(list3); System.out.println(list4); } ``` 结果: ``` [68, 98, 11, 31, 72, 69, 67, 49, 49, 34, 37, 43, 8, 33, 0, 2, 84, 11, 3, 72, 17, 38, 60, 55, 76, 88, 68, 5, 25, 11, 49, 44, 44, 78, 72, 70, 4, 30, 79, 33, 49, 77, 28, 3, 21, 88, 50, 55, 35, 4, 70, 82, 12, 67, 6, 4, 42, 3, 24, 12, 97, 94, 46, 81, 54, 7, 81, 29, 2, 54, 19, 70, 54, 36, 70, 10, 45, 73, 33, 56, 17, 49, 71, 40, 8, 51, 15, 89, 16, 48, 80, 28, 17, 58, 5, 22, 78, 82, 34, 5] [68, 98, 11, 31, 72, 69, 67, 49, 49, 34, 37, 43, 8, 33, 0, 2, 84, 11, 3, 72, 17, 38, 60, 55, 76, 88, 68, 5, 25, 11, 49, 44, 44, 78, 72, 70, 4, 30, 79, 33, 49, 77, 28, 3, 21, 88, 50, 55, 35, 4, 70, 82, 12, 67, 6, 4, 42, 3, 24, 12, 97, 94, 46, 81, 54, 7, 81, 29, 2, 54, 19, 70, 54, 36, 70, 10, 45, 73, 33, 56, 17, 49, 71, 40, 8, 51, 15, 89, 16, 48, 80, 28, 17, 58, 5, 22, 78, 82, 34, 5] ``` 相同seed下,强伪随机数生成的结果也是一样的。。。 --END--
发表评论