random()、对数器
简介:当我们手写了一个排序算法后,往往手写几给数组进行测试。但这是小样本的测试不具有普遍性,这是就要采用对数器来生成大样本来检验算法。 对数器的作用:自动生成随机样本,让我们不再依赖线上测试也能完成算法的检验。实现:对数器依赖于random()随机函数,使得可以生成长度随机,值也随机的数组。
一、random() 随机函数
-
随机数函数"Math.random()":他会等概率返回[0,1)中间的一个随机数。
//main方法 public static void main(String[] args) { //1. random随机性测试 System.out.println("randomTest(0.5) = " + randomTest(0.5)); } /** * random随机性测试 * * @author lihaojie * @date 2022/12/10 10:56 * @param max [0,max) * @return double */ public static double randomTest(double max){ //测试次数 int testNumber =1000000; int count=0; for (int i = 0; i < testNumber; i++) { //如果生成的数小于max则count加1,否则不变 count = (Math.random() < max) ? ++count : count; } return (double) count/testNumber; }
-
random()往往只能生成[0,1)之间的double类型的小数,有时这不能满足我们于是对其改进。
//main方法 public static void main(String[] args) { //2. randomPlus test for (int i = 0; i < 100; i++) { System.out.println("randomPlus(0) = " + randomPlus(9)); } //3.xToxPower2 test int count=0; double x=0.5; //测试10000次 for (int i = 0; i <10000; i++) { if (xToxPower2()<x) count++; } //输出改进和的概率 System.out.println("(double) count/10000 = " + (double) count / (double) 10000); //输出x^2的概率 System.out.println("Math.pow(x,2) = " + Math.pow(x, 2)); } /** * random改造,让其产生[0,multiple)随机整数 * * @author lihaojie * @date 2022/12/10 11:08 * @param multiple 倍数 * @return int */ public static int randomPlus(int multiple){ return (int) (Math.random()*multiple); } /** * random是线性的,如何改造成x^2 * * @return double * @author lihaojie * @date 2022/12/10 11:24 */ public static double xToxPower2() { /* 为什么调用两个random再去最小值,就能实现x^2的效果呢? 因为当调用两次random,它两个是独立的,可以看作两次独立重复实验,当两次结果的最大值还要小于x,则说明这两次都小于 x。我们知道random是等概率的,一次小于x=0.5的概率是p=1/2,那么在两次独立重复实验中同时小于x=0.5的概率则是 p^2 */ return Math.max(Math.random(), Math.random()); }
-
经典面试题
面试题1: f1()等概率随机产生1,2,3,4,5 。请利用f1()得到目标函数 goal() 使其随机产生1-7的整数
// 面试题1: 给你一个f1(),可随机产生1,2,3,4,5。现在我让使用f1()构造一个f2()使得其随机产生1,2,3,4,5,6,7 /*解析: 我们可用随机函数f1()构造一个随机种子函数,让其随机产生0,1。当我们得到随机种子函数,再将其改造成生成1-7的随机函数 */ //第一步: 利用f()函数构造0,1的随机种子函数f2() public static int f2(){ /*我们知道f1()返回1,2,3,4,5的概率均是p=0.2 所以我们这个规定,当f1()返回1,2时对应0,4,5时对应1,3则重新调用f1()知道不在等于3为止。这样就等概率的返回0,1了*/ int a; do { a = f1(); }while (a==3); return a<3 ? 0:1; } //第二步: 实现0-7等概率返回 public static int f3(){ //调用1次f2()会产生两种结果,那么调用三次就会组合出8中结果,例如:000,001,010,…… ,111 //而这恰好是0-7的所对应的二进制 return (f2()<<2)+(f2()<<1)+(f2()<<0); } //第三步: 0-7 转换为 0-6等概率返回 public static int f4(){ /*f4()的思路与f2()相同,我们既然能随机生成0-7了,那我们将f3()>6时重新调用f3(),就可随机生成0-6*/ int ans; do{ ans=f3(); }while (ans==7); return ans; } //第四步: 0-6 --转变-->1-7 public static int goal(){ return f4()+1; }
面试题2:
f1()不等概率产生0,1。f1()==0的概率为p,f1() ==1的概率为1-p。请利用f1()得到目标函数 goal() 使其随机产生1-7的整数。
思路:我们调用两次f1()函数,其中00与11情况都不要(不要:再调用两次,直到结果不是这两个)。则10,01为将等概率出现,概率:p*(1-P)。我们规定10 -->0; 01–>1。这就找到了随机种子函数,可随机产生0,1。之后方法如上。
二、对数器
public static void main(String[] args) {
//对数器的使用
for (int i = 0; i < testTimes; i++) {
int maxLen=100;
int maxValue=100;
int[] arr1=arrRandom(maxLen,maxValue);
int[] tmp = arr1.clone();
insertSort2(arr1);
//检测排序是否成功
for (int j = 1; j < arr1.length; j++) {
//保证相邻两个数之间,前一个数都小,才说明数组升序
if (arr1[j-1]>arr1[j]){
System.out.println("出错了,出错数组为:");
for (int count1 = 0; count1 < tmp.length; count1++) {
System.out.print(tmp[count1]);
}
System.out.println("结果为:");
for (int count1 = 0; count1 < arr1.length; count1++) {
System.out.print(arr1[count1]);
}
}
}
}
}
/**
* 对数器:返回一个arr,长度 ->[0,maxLen-1) arr中的每个值 -> [0,maxValue-1)
*
* @author lihaojie
* @date 2022/12/10 15:08
* @param maxLen 数组长度上限
* @param maxValue 值上限
* @return int[]
*/
public static int[] arrRandom(int maxLen,int maxValue){
int[] arr=new int[(int) (Math.random()*maxLen)];
for (int i = 0; i < arr.length; i++) {
arr[i]=(int) (Math.random()*maxValue);
}
return arr;
}