【数据结构】随机函数

1. Math.Random 函数

Math.random 函数以等概率返回 [0, 1) 的值。

 int getTimes = 1000000;
 int count = 0;

 // 验证 random 函数是否真的遵循等概率原则
 for(int i = 0; i< getTimes; i++){
     double x = Math.random();
     if(x < 0.3){
         count++;
     }
 }
 System.out.println("小于0.3的概率为" + (double) count / (double) getTimes);

等概率返回 [0, k) 的值

/*
 * 返回概率 y = x ^ 2
 * x = [0, 1)
 */
public static double xToPower2() {
    // 比如小于 0.3
    // 两个随机函数都要小于 0.3 属于这个值,因此就是 03 * 0.3
    return Math.max(Math.random(), Math.random());
}

 // [0, k-1) 等概率分布验证
 int k = 10;
 int[] counts = new int[k];
 for(int i = 0; i< getTimes; i++) {
    counts[getRandomInt(k)]++;
 }

 for(int i = 0; i < k; i++) {
     System.out.println("数" + i + "有" + counts[i] + "个");
 }

返回 x^2 的概率

/**
 * 返回概率 y = 1 - (1 - x) ^ 2
 * x = [0, 1)
 */
public static double xToPower2_() {
    // 比如小于 0.3
    // 先求不到 0. 3 的概率 (1 - 0.3) ^ 2
    // 得到 0.3 的概率就为  1 - (1 - 0.3) ^ 2
    return Math.min(Math.random(), Math.random());
}

count = 0;
double x = 0.17;
for (int i = 0; i < getTimes; i++) {
    double ans = xToPower2();
    if (ans < x) {
        count++;
    }
}

System.out.printf("原有概率:%f\n", x * x);
System.out.printf("实际概率:%f\n", (double) count / getTimes);

返回 1 - (1 - x)^2 的概率

/**
 * 返回概率 y = 1 - (1 - x) ^ 2
 * x = [0, 1)
 */
public static double xToPower2_() {
    // 比如小于 0.3
    // 先求不到 0. 3 的概率 (1 - 0.3) ^ 2
    // 得到 0.3 的概率就为  1 - (1 - 0.3) ^ 2
    return Math.min(Math.random(), Math.random());
}

2. 0 - 1 发生器

问题:由 1 - 5 等概率函数得到 1 - 7 等概率函数

首先由 1-5 随机写出 0-1 随机发生器(将 3 概率等分给1 2 和 4 5,1 2 为 0,4 5 为 1),7 的二进制数为 111,所以写出 01 随机后根据三位二进制数随机得到 0-7,强制将为 7 的结果均匀分给其他结果(0-6)等到 0 - 6 发生器,再将结果 +1 得到 1-7 随机。

/**
 * 1 - 5 等概率发生器.
 */
public static int oneToFiveRandom() {
    return (int) (Math.random() * 5) + 1;
}
/**
 * 0 1 发生器.
 */
public static int zeroOneRandom() {
   int ans;
   do {
       ans = oneToFiveRandom();
   } while (ans == 3);

   return ans <= 2 ? 0 : 1;
}
/**
 * 0 - 7 发生器.
 */
public static int zeroToSevenRandom() {
    return (zeroOneRandom() << 2) + (zeroOneRandom() << 1) + (zeroOneRandom());
}
/**
 * 0 - 6 发生器.
 */
public static int zeroToSixRandom() {
    int ans;
    do {
        ans = zeroToSevenRandom();
    }while (ans == 7);

    return ans;
}
/**
 * 1 - 7 发生器.
 */
public static int oneToSevenRandom() {
    return zeroToSixRandom() + 1;
}

counts = new int[8];
for(int i = 0; i< getTimes; i++){
    counts[oneToSevenRandom()]++;
}

for(int i = 0; i < 8; i++){
    System.out.println("数" + i + "有" + counts[i] + "个");
}

由此可得从 a-b 随机到 c-d 随机:先由 a-b 搞出 01 的等概率发生器,再做出 0-(d-c) 等概率(二进制)。

3. 由 01 不等概率到 01 等概率

问题:函数 f() 以一定概率返回 0 和 1 但不是等概率,0 的概率为 p,1 的概率为 1 - p,要求得到函数 g() 等概率返回 0 和 1

解法:随机两次 f,如果两次值相同舍弃。因为两次不同的值的概率(10 或 01)是相同的,都是 p * (1 -p)

public static int f() {
	return Math.random() < 0.84  ? 0 : 1;
}
public static int g() {
    int ans;
    do {
        ans = f();
    } while (ans == f());
    
    return ans;
}

4 对数器

生成随机样本自己做比对的机器

/**
 * 生成最大长度为 maxLen,最大值为 maxValue 的随机数组.
 */
public static int[] random(int maxLen, int maxValue) {
    int len = (int) (Math.random() * maxLen) + 1;
    int[] arr = new int[len];

    for (int i = 0; i < len; i++) {
        arr[i] = (int) (Math.random() * maxValue) + 1;
    }

    return arr;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值