content: package class02;
  
  public class Code02_RandToRand {
  
  	// 此函数只能用，不能修改
  	// 等概率返回1~5
  	public static int f() {
  		return (int) (Math.random() * 5) + 1;
  	}
  
  	// 等概率得到0和1
  	public static int a() {
  		int ans = 0;
  		do {
  			ans = f();
  		} while (ans == 3);
  		return ans < 3 ? 0 : 1;
  	}
  
  	// 等概率返回0~6
  	public static int b() {
  		int ans = 0;
  		do {
  			ans = (a() << 2) + (a() << 1) + a();
  		} while (ans == 7);
  		return ans;
  	}
  
  	// 等概率返回1~7
  	public static int c() {
  		return b() + 1;
  	}
  
  	// 这个结构是唯一的随机机制
  	// 你只能初始化并使用，不可修改
  	public static class RandomBox {
  		private final int min;
  		private final int max;
  
  		// 初始化时请一定不要让mi==ma
  		public RandomBox(int mi, int ma) {
  			min = mi;
  			max = ma;
  		}
  
  		// 13 ~ 17
  		// 13 + [0,4]
  		public int random() {
  			return min + (int) (Math.random() * (max - min + 1));
  		}
  
  		public int min() {
  			return min;
  		}
  
  		public int max() {
  			return max;
  		}
  	}
  
  	// 利用条件RandomBox，如何等概率返回0和1
  	public static int rand01(RandomBox randomBox) {
  		int min = randomBox.min();
  		int max = randomBox.max();
  		// min ~ max
  		int size = max - min + 1;
  		// size是不是奇数，odd 奇数
  		boolean odd = (size & 1) != 0;
  		int mid = size / 2;
  		int ans = 0;
  		do {
  			ans = randomBox.random() - min;
  		} while (odd && ans == mid);
  		return ans < mid ? 0 : 1;
  	}
  
  	// 给你一个RandomBox，这是唯一能借助的随机机制
  	// 等概率返回from~to范围上任何一个数
  	// 要求from<=to
  	public static int random(RandomBox randomBox, int from, int to) {
  		if (from == to) {
  			return from;
  		}
  		// 3 ~ 9
  		// 0 ~ 6
  		// 0 ~ range
  		int range = to - from;
  		int num = 1;
  		// 求0～range需要几个2进制位
  		while ((1 << num) - 1 < range) {
  			num++;
  		}
  
  		// 我们一共需要num位
  		// 最终的累加和，首先+0位上是1还是0，1位上是1还是0，2位上是1还是0...
  		int ans = 0;
  		do {
  			ans = 0;
  			for (int i = 0; i < num; i++) {
  				ans |= (rand01(randomBox) << i);
  			}
  		} while (ans > range);
  		return ans + from;
  	}
  
  	public static void main(String[] args) {
  		System.out.println("测试开始");
  		// Math.random() -> double -> [0,1)
  		//
  
  		int testTimes = 10000000;
  		int count = 0;
  		for (int i = 0; i < testTimes; i++) {
  			if (Math.random() < 0.75) {
  				count++;
  			}
  		}
  		System.out.println((double) count / (double) testTimes);
  
  		System.out.println("=========");
  
  		// [0,1) -> [0,8)
  		count = 0;
  		for (int i = 0; i < testTimes; i++) {
  			if (Math.random() * 8 < 5) {
  				count++;
  			}
  		}
  		System.out.println((double) count / (double) testTimes);
  		System.out.println((double) 5 / (double) 8);
  
  		int K = 9;
  		// [0,K) -> [0,8]
  
  		int[] counts = new int[9];
  		for (int i = 0; i < testTimes; i++) {
  			int ans = (int) (Math.random() * K); // [0,K-1]
  			counts[ans]++;
  		}
  		for (int i = 0; i < K; i++) {
  			System.out.println(i + "这个数，出现了 " + counts[i] + " 次");
  		}
  
  		System.out.println("=========");
  
  		count = 0;
  		double x = 0.17;
  		for (int i = 0; i < testTimes; i++) {
  			if (xToXPower2() < x) {
  				count++;
  			}
  		}
  		System.out.println((double) count / (double) testTimes);
  		System.out.println((double) 1 - Math.pow((double) 1 - x, 2));
  
  		System.out.println("==========");
  		count = 0;
  		for (int i = 0; i < testTimes; i++) {
  			if (f2() == 0) {
  				count++;
  			}
  		}
  		System.out.println((double) count / (double) testTimes);
  
  		System.out.println("==========");
  
  		counts = new int[8];
  		for (int i = 0; i < testTimes; i++) {
  			int num = g();
  			counts[num]++;
  		}
  		for (int i = 0; i < 8; i++) {
  			System.out.println(i + "这个数，出现了 " + counts[i] + " 次");
  		}
  
  	}
  
  	// 返回[0,1)的一个小数
  	// 任意的x，x属于[0,1)，[0,x)范围上的数出现概率由原来的x调整成x平方
  	public static double xToXPower2() {
  		return Math.min(Math.random(), Math.random());
  	}
  
  	// lib里的，不能改！
  	public static int f1() {
  		return (int) (Math.random() * 5) + 1;
  	}
  
  	// 随机机制，只能用f1，
  	// 等概率返回0和1
  	public static int f2() {
  		int ans = 0;
  		do {
  			ans = f1();
  		} while (ans == 3);
  		return ans < 3 ? 0 : 1;
  	}
  
  	// 得到000 ~ 111 做到等概率 0 ~ 7等概率返回一个
  	public static int f3() {
  		return (f2() << 2) + (f2() << 1) + f2();
  	}
  
  	// 0 ~ 6等概率返回一个
  	public static int f4() {
  		int ans = 0;
  		do {
  			ans = f3();
  		} while (ans == 7);
  		return ans;
  	}
  
  	public static int g() {
  		return f4() + 1;
  	}
  
  	// 你只能知道，x会以固定概率返回0和1，但是x的内容，你看不到！
  	public static int x() {
  		return Math.random() < 0.84 ? 0 : 1;
  	}
  
  	// 等概率返回0和1
  	public static int y() {
  		int ans = 0;
  		do {
  			ans = x();
  		} while (ans == x());
  		return ans;
  	}
  
  }
  