1.1.35 Dice simulation 筛子模拟

    该题目来源于Robert Sedgewick 的《算法》。

1.1.37 Dice simulation. The following code computes the exact probability distribution for the sum of two dice:

        
        int SIDES = 6;
        double[] dist = new double[2*SIDES+1];
        for (int i = 1; i <= SIDES; i++) {
            for(int j=1; j <= SIDES; j++){
                dist[i+j] += 1.0;
            }
        }
        logger.info("dist:" + Arrays.toString(dist));
        double sum = 0.0;
        for (double var : dist) {
            sum += var;
        }
        logger.info("dist sum: " + sum);
        for(int k=2; k <= 2*SIDES; k++){
            dist[k] /= SIDES * SIDES;
        }

The vlaue dist[i] is the probability that the dice sum to i. Run experiments to validate this calculation simulating N dice throws, keeping track of the frequencies of occureence of each value when you compute the sum of two random integers between 1 and 6. How large does N have be before your empirical results match the exact results to three decimal places?

 

1.1.37 模拟掷筛子。下面的代码计算两个筛子点和的精确的可能性分布:

dist[i]的值为筛子和为i的可能性。模拟N次掷筛子去验证这个计算,当你计算两个随机在1到6之间的随机整数和的时候,保持跟踪每个值出现的频次。 在你的经验结果和准确结果匹配,精确到小数点后三位之前,N的值应该多大?

 

分析:

    两个6面的筛子,同时掷两个筛子,可能出现的组合有6*6中情况。这6*6中情况中,和为i+j的情况有:dist[i+j]  += 1 种。

    详细的代码如下:

import java.util.Arrays;
import java.util.logging.Logger;

import utils.chapter1.StdRandom;

/**
 * 
 */
public class Exercise1135DiceSimulation {

    private static final Logger logger = Logger.getLogger("basicprogrammingmodel.exercises");

    private static final int SIDES = 6;
    

    public static void main(String[] args) {
        //diceExactProbabilityDistribution();
        int N = findSufficientN(.001);
        logger.info("N have to be " + N);
    }
    /**
     * 精确值的概率分布
     */
    public static double[] diceExactProbabilityDistribution(){
        double[] dist = new double[2*SIDES+1];
        for (int i = 1; i <= SIDES; i++) {
            for(int j=1; j <= SIDES; j++){
                dist[i+j] += 1.0;
            }
        }
        logger.info("dist:" + Arrays.toString(dist));
        double sum = 0.0;
        for (double var : dist) {
            sum += var;
        }
        logger.info("dist sum: " + sum);
        for(int k=2; k <= 2*SIDES; k++){
            dist[k] /= SIDES * SIDES;
        }
        logger.info("dist:" + Arrays.toString(dist));
        return dist;
    }
    /**
     * 掷筛子
     * @return
     */
    private static int diceThrow(){
        return StdRandom.uniform(SIDES) + 1;
    }
    /**
     * 掷N次筛子,两个筛子和的概率分布
     * @param N
     * @return
     */
    private static double[] trackNDiceThrowsProbabilityResult(int N){
        double[] dist = new double[SIDES*2+1];
        for (int i = 0; i < N; i++) {
            int dice1 = diceThrow();
            int dice2 = diceThrow();
            dist[dice1 + dice2] += 1.0;
        }
        for (int i = 2; i < dist.length; i++) {
            dist[i] /= N;
        }
        return dist;
    }
    /**
     * 最大的差距
     * @param exactResults
     * @param empiricalResults
     * @return
     */
    private static double maxDisparity(double[] exactResults, double[] empiricalResults){
        double max_disp = Double.NEGATIVE_INFINITY;
        int indexMax = Math.max(exactResults.length, empiricalResults.length);
        for (int i = 2; i < indexMax; i++) {
            double disp = Math.abs(exactResults[i] - empiricalResults[i]);
            if (max_disp < disp) max_disp = disp;
        }
        return max_disp;
    }
    /**
     * 查找足量的N
     * @param disparity
     * @return
     */
    private static int findSufficientN(double disparity){
        double[] theoretical_dist = diceExactProbabilityDistribution();
        int N=35;
        double[] experiment_dist;
        do{
            N += 1;
            experiment_dist = trackNDiceThrowsProbabilityResult(N);
        }while(maxDisparity(theoretical_dist,experiment_dist) > disparity);
        return N;
    }

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值