描述RANDOM(a,b)的过程的一种实现,它只调用RANDOM(0,1)。作为a和b的函数,你的程序的期望运行时间是多少?(RANDOM(0,1)以等概率输出0或者1,RANDOM(a,b)以等概率输出[a,b]之间的数(整数))
要RANDOM(a,b)等概率输出[a,b]之间的数,只要等概率得到[0,b-a]之间的一个数即可。既然可以通过RANDOM(0,1)得到1或者0,这时候就能等概率把[0,b-a]区间划分成更小的区间,假设当得到1时区间缩小为[(b-a)/2,b-a],0时为[0,(b-a)/2]。如此递归,最终得到只有一个整数的区间假如为[x,x],此时a+x就是最终的结果。
上面的思路看似很美好,但是有一个蛮致命问题没考虑到,就是[0,b-a]中b-a+1必须为2^x(2的幂)才能保证等概率。举个栗子,[0,2]中有3个数{0,1,2}这时得到2的概率明显比0跟1的大。这边的解决办法是扩充区间保证区间中的整数个数是2的幂。当得到的整数比b-a大则重新执行..如此
1 // Random.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include "windows.h" 6 #include "stdio.h" 7 #include "math.h" 8 #include "time.h" 9 10 /* 11 实现RANDOM(0,1)的函数 12 */ 13 14 int eitherRand() 15 { 16 return rand()%2; 17 } 18 /* 19 执行递归 20 */ 21 long rand(int *arr, int beg, int end) 22 { 23 if(beg == end) 24 { 25 return beg; 26 } 27 else 28 { 29 return eitherRand()==0?rand(arr,beg,(beg+end)/2):rand(arr,(beg+end)/2+1,end); 30 } 31 } 32 int main() 33 { 34 int a=2; 35 int b=7; 36 int dif=b-a+1; 37 long rs =1; 38 int exp = 0; 39 while(rs<dif) 40 { 41 rs = rs*2; 42 exp ++; 43 } 44 int *arr = (int *)malloc(rs*sizeof(long)); 45 //随机种子,设置一直就可以了。重复设置会产生相同的值 46 srand((unsigned)time(0)); 47 int rdNum = rand(arr,0,rs-1); 48 while(rdNum>dif) 49 { 50 rdNum = rand(arr,0,rs-1); 51 } 52 printf("%d",rdNum+a); 53 system("pause"); 54 return 0; 55 }
时间: 2024-10-16 12:27:36