粉笔面试——生成随机数(根据rand7()生成rand10())
今天面试并不是太顺利,一连好几个题都摸不着头脑,所以记录一下。
已知:
rand7() 得到0-6
求:
rand10()
0-9
想法
朴素想法:(X)
- rand7() -> rand10()
- rand7()只能生成0-6
- 所以rand10() = rand7+ rand7%4;
- 不对.因为 rand10() = 2, 可能有多种组合,一个是0和2,还有一个2和0,还有1和1;
- 但是rand10()=9;只有一种组合即6和3;
- 这样概率就不等了.
由大的随机数求小的随机数可以吗?(√)
假如由rand10() -> rand7()可以吗?
答案是可以的.
只需要rand10()生成0-6即可.如果>6就不让输出
其实很好解释:
- rand10生成随机数是等概率的,所以生成0-6之间的数当然也是等概率的.
int rand7(){ res = 7 while (res > 6) res = rand10(); return res; }
这时的想法是能生成一个[0-N]的数,其中N>=9就行
res = rand7()*7 + rand7()+1
res可以等概率的生成1~49.原因如下:
- rand7()*7 可以生成 0,7,14,21,28,35,42.这7个数都是等概率1/7
- rand7()*7 + rand7()+1正好能生成1~49
所以函数为:
public static int rand10(){ int res = 49; //为什么不是res>10 while (res>40) { res = rand7()*7 + rand7()+1; } return res%10; }
为什么不是res>10?
原因有两个:
- 输出结果一致吗?(√)
- 输出1-40,概率是相同,res%10
- 输出1-10,概率是相同,res%10
- 两个res%10结果是一致的
- 概率一样吗?
- 输出1-10,while一次能输出的概率为 10/49
- 输出1-40,while一次能输出的概率为40/49
- 显然能减少循环.
综上,不使用res>10,使用res>40,能减少循环.
java代码如下:
import java.util.Arrays; import java.util.Random; /** * 已知: * rand7() * 0-6 * 求: * rand10() * 0-9 */ public class randomNumber { public static int rand7(){ return new Random().nextInt(7); } public static int rand10(){ int res = 49; //为什么是40不是10 //如果是10的话,那么while会循环很多次,因为概率输出的概率为10/49 //这时会输出1-40,其概率是相同,res%10和输出1-10的res%10效果一致 //但是能够输出的概率变为40/49,概率大增 while (res>40) { res = rand7()*7 + rand7()+1; } return res%10; } public static void main(String[] args) { double[] print = new double[10]; for (int i = 0; i < 1000000; i++) { print[rand10()] += 1; } for (int i = 0; i < print.length; i++) { print[i] = print[i] /1000000; } System.out.println(Arrays.toString(print)); } }
输出结果: (概率一致)
[0.097554, 0.122075, 0.097362, 0.097936, 0.097623, 0.097441, 0.097284, 0.097415, 0.097377, 0.097933]