一、题目
给定一个函数random1,它可以等概率的随机返回整数1-7,请利用该函数完成新函数random2,使其等概率的随机返回整数0或1。
二、解答
由于返回值只有2个,且等概率的,所以各占50%。但由于函数random1返回整数1-7的概率都是1/7,不容易直接均分两份,所以稍一思索,我写了如下的代码:
/**
* 等概率返回0或1
*/
public static int random2() {
int n = random1();
if(n > 3) {
return 1;
}
if(n < 3) {
return 0;
}
return random1();
}
/**
* 给定函数:等概率返回整数1-7
*/
public static int random1() {
return (int)(Math.random() * 7) + 1;
}
三、优化
面试官看过我的代码,不太满意。他说:你过于信任我提供的函数random1,如果我的函数有问题呢?你再考虑一下,看看能不能再改进下?
我一听,觉得对方也有道理,于是添加了返回值校验,更新代码如下:
/**
* 等概率返回0或1
*/
public static int random2() {
int n = random1();
if(n < 1 || n > 7) {
return -1; //返回异常值或抛出异常以便于调用者处理
}
if(n > 3) {
return 1;
}
if(n < 3) {
return 0;
}
return random1();
}
我很快又把代码递给对方了,心想这下可以了吧?结果对方瞄了一眼就说:如果我的函数一直返回4呢?我的程序可以运行,但到你的程序就出现死循环了啊?是不是可以加上一个次数校验?如果给定函数连续出现几次4就退出?
是啊!应该有次数检测,这样就可以避免出现死循环了。
int num = 0; //连续返回4的次数
final int MAX_TIME_4 = 5; //最多连续返回4的次数
/**
* 等概率返回0或1
*/
public static int random2() {
int n = random1();
if(n < 1 || n > 7) {
return -1; //返回异常值或抛出异常以便于调用者处理
}
if(n > 3) {
num = 0;
return 1;
}
if(n < 3) {
num = 0;
return 0;
}
num ++;
if(num >= MAX_TIME_4){
return -2; //返回异常值或抛出异常以便于调用者处理
}
return random1();
}
可是MAX_TIME_4值应该是多少呢?也就是说4连续出现几次可以判定为死循环呢?3次?5次?10次?100次?似乎都不太合适吧?
回过头再看看题目,豁然开朗:题目说了给定函数random1可以等概率的随机返回整数1-7的,为什么还会出现这种一直返回4的低级错误呢?我为什么又要做这种检测呢?
实际项目中,你们又是怎么处理这种问题呢?欢迎留言赐教、探讨~