/** * @return 返回0或1 * @description 等概率返回0、1 */ publicstaticintbit(){ int res = 0; do { res = rand5(); } while (res == 3); return res < 3 ? 0 : 1; }
/** * 等概率返回0~2^bits-1之间的所有数 * * @param bits 二进制位数 * @return 返回0~2^bits-1之间的某个数 */ publicstaticintgenerate(int bits){ int res = 0; for (int i = 0; i < bits; i++) { res += bit() << i; } return res; }
/** * @return 返回1~7之间的某个整数 * @description 等概率返回1~7之间的所有整数 */ publicstaticintrand7(){ // 可以发现[1, 7]可以由[0, 6] + 1构成,于是考虑如何等概率返回[0, 6] int res = 0; do { res = generate(3); } while (res == 7); return res + 1; }
publicstaticvoidmain(String[] args){ int[] counts = newint[10]; int N = 1000000; for (int i = 0; i < N; i++) { counts[rand7()]++; } for (int i = 1; i <= 7; i++) { System.out.printf("%d出现%d次\n", i, counts[i]); } } }
测试\(1000000\)次的结果:
image-20220910173239248
由rand(a, b)返回rand(c, d)
其中rand(a, b)函数可以等概率返回[a, b]之间的所有数,需要使用rand(a, b)生成rand(c, d)其中d - c != b - a。
publicclassRandRange{ publicstaticintrandAB(int a, int b){ int diff = b - a + 1; return (int) (Math.random() * diff) + a; }
publicstaticintbit(int a, int b){ // 使用randAB(a, b)等概率返回0、1 int res = 0; // 注意如果[a, b]中有奇数个数字则舍弃中间数字 // 如果[a, b]中有偶数个数字则直接划分即可 int count = b - a + 1; int mid = a + (b - a) / 2; if (count % 2 == 1) { do { res = randAB(a, b); } while (res == mid); return res < mid ? 0 : 1; } else { res = randAB(a, b); return res <= mid ? 0 : 1; } }
publicstaticintrandCD(int a, int b, int c, int d){ // 和rand7()思路一致, 先生成[0, x], 而后 + c即可 int x = d - c; int bits = 0; // 先求得x的二进制位数 int tmp = x; do { tmp >>= 1; bits++; } while (tmp != 0); int res = 0; do { res = 0; for (int i = 0; i < bits; i++) { res += (bit(a, b) << i); } } while (res > x); return res + c; }
publicstaticvoidmain(String[] args){ int N = 1000000; int a = 10, b = 20; int c = 40, d = 100; int[] counts = newint[b + 1]; for (int i = 0; i < N; i++) { counts[randAB(a, b)]++; } for (int i = a; i <= b; i++) { System.out.printf("%d出现%d次\n", i, counts[i]); } counts = newint[d + 1]; for (int i = 0; i < N; i++) { counts[randCD(a, b, c, d)]++; } for (int i = c; i <= d; i++) { System.out.printf("%d出现%d次\n", i, counts[i]); } } }
publicstaticintf(){ // 假定以3/4概率返回0, 1/4概率返回1 int res = 0; res = (int) (Math.random() * 4) + 1; return res <= 3 ? 0 : 1; }
publicstaticintg(){ int res = 0; do { res = f(); } while (res == f()); return res; }
publicstaticvoidmain(String[] args){ int N = 100000; int[] counts = newint[2]; for (int i = 0; i < N; i++) { counts[g()]++; } for (int i = 0; i <= 1; i++) { System.out.printf("%d出现了%d次\n", i, counts[i]); } } }