看到C#区此题讨论的比较火,转过来大家一起讨论讨论。已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10,要求考虑每个数字出现的概率问题。
最近比较忙,很少上来看,为了庆祝国庆顺便散个分。
散分规则:
1、达到题目要求且给出算法说明的加分。
2、在第1点的基础上算法效率高的多加分。
3、只写出算法但没有说明的视情况加分。
最近比较忙,很少上来看,为了庆祝国庆顺便散个分。
散分规则:
1、达到题目要求且给出算法说明的加分。
2、在第1点的基础上算法效率高的多加分。
3、只写出算法但没有说明的视情况加分。
{
int nResult=0; while(true)
{
nResult=rand7();
if(nResult<=5)
break;
} while(true)
{
int n = rand7();
if (n==1)
continue;
else if(n>4)
nResult*=2;
else
nResult=nResult*2-1;
break;
}
return nResult ;
}挺好,转贴过来,概率10%。
2. 只需要前面 4*10 个数,所以舍弃后面的9个数
3. 将8 9 10 11 转化为 1,12 13 14 15 转化为 2,……,44 45 46 47 转化为 10。公式是 (a-4)/4
int rand10(){int a;while( (a=rand7()*7+rand7()) > 47 );return (a-4)/4;}
2 (2+1)/49 -> 3/49
3 (2+1)/49 -> 3/49
4 (2+1+4)/49 -> 7/49
5 (2+1+4)/49 -> 7/49
6 (2+1+4)/49 -> 7/49
7 (2+1+4)/49 -> 7/49
8 (1+4)/49 -> 5/49
9 4/49
10 4/49这样多简单~
public static int ran10() {
int a10 ;
while( (a10 = ran7()+ran7() - 1) > 10) ;
return a10;
}
说明
1 ran7()+ran7() - 1 1到13
2 10 之后的删去
3 返回
这个概率都是10%了,嘿嘿~
2,3,4,5,6,7,8,9,10,11,12,13,14
2=1+1 --概率=1/7 * 1/7 = 1/49
3=1+2=2+1 --概率=1/7 * 1/7 + 1/7 * 1/7 = 2/49
4=1+3=2+2=3+1 --3/49
5=1+4=2+3=3+2=4+1 --4/49
6=1+5=2+4=3+3=4+2=5+1 -- 5/49
7=1+6=2+5=3+4=4+3=5+2=6+1 --6/49
8=1+7=2+6=3+5=4+4=5+3=6+2=7+1 --7/49
9=2+7=3+6=4+5=5+4=6+3=7+2 --6/49
10=3+7=4+6=5+5=6+4=7+3 --5/49
11=4+7=5+6=6+5=7+4 --4/49
12=5+7=6+6=7+5 --3/49
13=6+7=7+6 --2/49
14=7+7 --1/49
用rand7()+rand7()结果%10
1==11%10 --概率4/49
2==2%10==12%10 --1/49+3/49=4/49
3==3%10==13%10 --2/49+2/49=4/49
4==4%10==14%10 --3/49+1/49=4/49
5==5%10 --4/49
6==6%10 --5/49 去掉3+3的情况 --4/49
7==7%10 --6/49 去掉3+4和4+3的情况 --4/49
8==8%10 --7/49 去掉3+5和4+4和5+3的情况 --4/49
9==9%10 --6/49 去掉4+5和5+5的情况 --4/49
0==10%10 --5/49 去掉 5+5的情况 --4/49
可见,当r=(rand7()+rand7())%10大于5的时候,去掉上述的情况,就可以满足0-9的概率就都是4/49(也就是0-9的概率都是10%)代码例子
int rand10() {
int r1, r2, r3=0;
while (true) {
r1 = rand7();
r2 = rand7();
r3 = (r1+r2)%10;
if ((r3>5 || r3==0)
&& (Math.abs(r1-r2) <= (r3==8 ? 2 : 1))) continue;
return r3+1;
}
}
if(num>=1&&num<=10)
return num;
"-1" 为了最小可以得到num=1
而两次rand7()的概率分布是 7*7 = 49,不能满足上述的50和60,所以4个数一组需要40个数,49可以满足
11L的思路和我的思路差不多,11L的每个数的概率是1/49,所以四个数一组就是4/49的概率,去掉58-56的9种情况,即去掉9/49,剩余的40/49平分到10个数字,我的思路也是找到4/49的概率组合,然后去掉9种概率,剩余的都是4/49的概率,也能达到平分,效率上可能11L要好一些,相对运算少一些,虽然去掉9种情况的判断上是两种都差不多
public static void main(String[] args) {
int i = getRandomNumber();
int j = getRandomNumber();
int n = i * 7 + j;
int k = n * 10;
if (k >= 0 && k < 49) {
System.out.println(1);
} else if(k >= 49 && k < 49 * 2) {
System.out.println(2);
} else if(k >= 49*2 && k < 49 * 3) {
System.out.println(3);
} else if(k >= 49*3 && k < 49 * 4) {
System.out.println(4);
} else if(k >= 49*4 && k < 49 * 5) {
System.out.println(5);
} else if(k >= 49*5 && k < 49 * 6) {
System.out.println(6);
} else if(k >= 49*6 && k < 49 * 7) {
System.out.println(7);
} else if(k >= 49*7 && k < 49 * 8) {
System.out.println(8);
} else if(k >= 49*8 && k < 49 * 9) {
System.out.println(9);
} else if(k >= 49*9 && k < 49 * 10) {
System.out.println(10);
}
}
private static int getRandomNumber() {
Random r = new Random();
return r.nextInt(7);
}
}
11 21 .......... 71
12 22 .......... 72
13 23 .......... 73
14 24 .......... 74
15 25 .......... 75
16 26 .......... 76
17 27 .......... 77然后取其中10个映射1-10,出现其它的过滤,这样1-10的概率每个应该为10%的。简单 清晰。
我的思路是(rand7()+rand7())%10,去掉>5的情况下前后两个rand7()的差距在某个范围内的9种情况,相对不太好理解,不过思路上是差不多的。
2) 再用 (n-10)/67 将取值范围限定到 1~10
//除了0为4/49,其它的是5/49
//(rand7()*7+rand7()-7)%10
for(int i=1;i<8;i++)
{
for(int j=1;j<8;j++)
{
System.out.printf("%2d,",(i*7+j-7)%10);
}
System.out.println();
}
//结果如下:
1, 2, 3, 4, 5, 6, 7,
8, 9, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 0, 1,
2, 3, 4, 5, 6, 7, 8,
9, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 0, 1, 2,
3, 4, 5, 6, 7, 8, 9,
2. 只需要前面 4*10 个数,所以舍弃后面的9个数
3. 将8 9 10 11 转化为 1,12 13 14 15 转化为 2,……,44 45 46 47 转化为 10。公式是 (a-4)/4
这方法可行
{
int a1 = rand7();
int a2 = rand7();
int a = a1 + a2;
if(a>10){
a = 10;
}
return a;
}
然后取除10取余数,余数应该是0到9之内的任意一个数吧,然后再加1
int rand10()
{
int a = rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7();
return a%10+1;
}
新手,要是错了的话,指出来就可以,别笑话~
然后取除10取余数,余数应该是0到9之内的任意一个数吧,然后再加1
int rand10()
{
int a = rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7()+rand7();
return a%10+1;
}
新手,要是错了的话,指出来就可以,别笑话~
可以这样来,0-0.7 1
0.7-1.4 2
1.4-2.1 3
2.1-2.8 4
2.8-3.5 5
3.5-4.2 6
4.2-4.9 7
4.9-5.6 8
5.6-6.3 9
6.3-7 10
太该就这意思,还需改进。。
引用7进制的做法保证得到随机数的概率相同。例如(rand7-1)*7+rand7得到是00-66之间的全部七进制数。且保证概率相同。
但是涉及到对10取余,为了保证取余后概率相同,这个区间一定是0-10的整数倍。
00-666(七进制)表示数的范围是0-2400,所以对10取余后得到0-9的概率相同。int rand10()
{
int sum=0;
for(int i=0; i<3; i++)
sum=7*sum+rand7()-1;
return sum%10+1;
}
保证概率相同,且时间复杂度可控。
详情见博客:http://blog.csdn.net/zmywhhit/article/details/6865521