题目: 1.从1-5随机到1-7随机 2.从a-b随机到c-d随机 3.01不等概率随机到01等概率随机
/**
* 题目:从1-5随机到1-7随机
* 思路:
* step1:利用f1函数得到一个 0,1等概率 f2函数
* step2:用3个二进制位表示,每个二进制位调用一个f2 得到 0~7等概率 f3 函数
* step3: 调用f3函数,如果得到7就重新调用,否则就返回 ,得到0~6等概率 f4 函数
* step4:f4函数加一
* @return
*/
//等概率随机返回1,2,3,4,5
public static int f1(){
return (int)Math.random()*5+1;
}
/**
* 随机机制,只能用f1
* 概率返回0和1
* 思路:
* 由于f1是等概率返回1,2,3,4,5 ,
* 调用f1,如果得到1,2则返回0,得到4,5 则返回1,得到3 则重新调用
*/
public static int f2(){
int ans = 0;
do{
ans = f1();
}while (ans == 3);
return ans < 3 ? 0 : 1;
}
//得到二进制位 000~111 做到等概率, 即 0~7等概率返回
public static int f3(){
int ans = (f2() << 2) + (f2() << 1)+ (f2() << 0);
return ans;
}
//0~6等概率返回一个
public static int f4(){
int ans = 0;
do{
ans = f3();
}while (ans == 7);
return ans;
}
public static int g(){
return f4()+1;
}
同理可得出: 从a-b随机到c-d随机 思路: 由 a-b 随机得到 0,1 等概率,即如果b-a+1 是奇数,则调该函数,如果得到前一半数字返回0,得到后一半数字返回1,得到中间的一个数则重新调,就得到了 0,1 等概率 1.要得到c-d 随机,可以先得到 0-(d-c)随机,然后再加c,就得到了0-d 随机, 2.要得到 0 - (d-c)随机 就要看需要几个二进制位了,1个二进制位可以得到0-2随机,两个二进制位可以得到0,3(2^0+2^1)随机,三个二进制位可以得到0,7(2^0+2^1+2^2)随机,····· 3.然后做do,while 多余的部分,重新调,否则就返回,得到 0 - (d-c)随机 4. 加c ,得到 c-d 随机
/**
* 题目:01不等概率随机到01等概率随机 , 例如x()函数,以p概率返回0,以1-p概率返回1,
* 思路:
* 用两个二进制位表示,调用两次f()函数,如果得到00(概率是p*p),重新调,如果得到11(概率是(1-p)*(1-p))重新调,
* 如果得到01(概率是p*(1-p))返回0,如果得到10(概率是(1-p)*p)返回1
* 由于 01(概率是p*(1-p)) 和10(概率是(1-p)*p) 是等概率的,所以只在这两种情况返回0或1,其他情况则重新调
* 例如有一个函数x(),你只知道,x会以固定概率返回0和1,但是x的内容,你看不到
* @return
*/
public static int x(){
return Math.random() < 0.84 ? 0 : 1;
}
//等概率返回0和1
public static int y(){
int ans = 0;
do {
ans = x();
}while (ans == x());
return ans;
}
任意的x,x属于[0,1),[0,1)范围内出现的数由原来的x调整成x的平方
/**
* 返回[0,1)范围内的一个数
* 任意的x,x属于[0,1),[0,1)范围内出现的数由原来的x调整成x的平方
* @return
*/
public static double xToXPower2(){
return Math.max(Math.random(),Math.random());
}
测试方法
public static void main(String[] args) {
int testTimes = 10000000;
int count = 0;
for (int i = 0; i < testTimes; i++) {
double ans = Math.random(); //产生[0,1)之间的数
if(ans < 0.3) count++;
}
//System.out.println((double)count/(double)testTimes);
//0~X 范围内 任意x出现的概率是X
double x = 0.7;
count = 0;
for (int i = 0; i < testTimes; i++) {
if(xToXPower2() < x) count++;
}
System.out.println((double)count/(double)testTimes);
System.out.println(Math.pow(x,2));
int[] counts = new int[8];
for (int i = 0; i < testTimes ; i++) {
int num = f3();
counts[num]++;
}
for (int i = 0; i < 8; i++) {
System.out.println(i+"这个数出现了 "+ counts[i] +"次");
}
}