0

任务:不公平的骰子(6 面)被滚动 n 次。1 的概率是 p1,2 的概率是 p2,依此类推。编写一个计算机程序,对于给定的 n (n<100),集合 (p1,p2,p3,p4,p5,p6) 和 $x \in [n,600n]$ 的概率将找到总和的概率骰子值小于 x。程序不能运行超过 5 分钟。这是一个额外的问题,会给我加分,但到目前为止没有人这样做。我怀疑像我这样的初学者计算机科学家也可以从这段代码中学习,因为我在网上找到了 0 帮助关于偏向骰子的帮助,并想出了类似轮盘赌的解决方案。我也有点想向世界展示我的方式。

我有 2 个解决方案 - 使用几何概率和统计概率。

我的问题是:1)我这样做是正确的还是我在某个地方出错了?2)你认为哪一个给我更好的答案几何或统计概率?我的直觉说它是几何的,因为它更可靠。我认为我的代码给我的答案是正确的——通常超过 0.99 ..... 我希望有人检查我的工作,因为我完全不确定,我想与其他人分享这段代码。

我更喜欢 Java,因为它比带有循环的 R 快得多,但我也为统计提供了 R 代码,它们非常相似,我希望这不是问题。

Java代码:

import java.util.ArrayList;


public class Statistical_prob_lisayl2_geometrical {

    public static double mean(ArrayList<Double> a) {
        double sum=0;
        int len = a.size();
        for (int i = 0; i < len; i++) {
            sum = sum + a.get(i);
        }
        return (sum/len);
    }

    public static double geom_prob(double p1,double p2,double p3,double p4,double p5,double p6){
        ArrayList<Double> prob_values = new ArrayList<Double>();

        int repeatcount = 1000000;
        int[] options = {1,2,3,4,5,6};
        int n = 50;
        double[] probabilities = {p1,p2,p3,p4,p5,p6};
        for (int i = 0 ; i < repeatcount ; i++ ) { // a lot of repeats for better statistical probability
            int sum = 0; //for each repeat, the sum is being computed
            for (int j = 0; j < n ; j++ ) { // for each repeat there is n cast of dies and we compute them here
                double probability_value=0; // the value we start looking from with probability
                double instant_probability = Math.random(); // we generate random probability for dice value
                    for (int k = 0; k < 6; k++ ) { // because we have 6 sides, we start looking at each probability like a roulette table
                        probability_value = probability_value + probabilities[k]; // we sum the probabilities for checking in which section the probability belongs to
                        if (probability_value>instant_probability) {
                            sum = sum + options[k]; // if probability belongs to certain area , lets say p3 to p4, then p3 is added to sum
                                break; // we break the loop , because it would give us false values otherwise
                        }
                    }
                }
            double length1 = (600*n)-n-(sum-n); //length of possible x values minus length of sum
            double length2 = 600*n-n;
            prob_values.add( (length1/length2) ); // geometric probability l1/l2

            }
        return mean(prob_values); // we give the mean value of a arraylist, with 1000000 numbers in it
    }
    public static double stat_prob(double p1,double p2,double p3,double p4,double p5,double p6){
        ArrayList<Double> prob_values = new ArrayList<Double>();

        int repeatcount = 1000000;
        int[] options = {1,2,3,4,5,6};
        int n = 50;
        double[] probabilities = {p1,p2,p3,p4,p5,p6};
        int count = 0;
        for (int i = 0 ; i < repeatcount ; i++ ) {
            int sum = 0;
            for (int j = 0; j < n ; j++ ) {
                double probability_value=0;
                double instant_probability = Math.random();
                    for (int k = 0; k < 6; k++ ) {
                        probability_value = probability_value + probabilities[k];
                        if (probability_value>instant_probability) {
                            sum = sum + options[k];
                                break;
                        }
                    }
                }
            int x = (int)Math.round(Math.random()*(600*n-n)+n);
            if( x>sum ) {
                count = count + 1;  
            }
        }
        double probability = (double)count/(double)repeatcount;
        return probability;
    }

    public static void main(String[] args) {
        System.out.println(stat_prob(0.1,0.1,0.1,0.1,0.3,0.3));
        System.out.println(geom_prob(0.1,0.1,0.1,0.1,0.3,0.3)); 
    }

}

代码:

repeatcount = 100000
options = c(1,2,3,4,5,6)
n = 50
probabilities = c(1/10,1/10,1/10,1/10,3/10,3/10)

count = 0
for (i in 1:repeatcount) {
sum = 0
for (i in 1:n) {
    probability_value=0
    instant_probability = runif(1,0,1)
    for (k in 1:6){
        probability_value = probability_value + probabilities[k]
        if (probability_value>instant_probability) {
            sum = sum + options[k] 
            break
        }
        }
    }
    x = runif(1,n,600*n)
    x
    sum
    if ( x> sum ) {
        count = count + 1   
    }
}
count
probability = count/repeatcount
probability
4

1 回答 1

0

这是你想要做的吗?

n <- 50     # number of rolls in a trial
k <- 100000 # number if trials in the simulation
x <- 220    # cutoff for calculating P(X<x)
p <- c(1/10,1/10,1/10,1/10,3/10,3/10) # distribution of p-side
X <- sapply(1:k,function(i)sum(sample(1:6,n,replace=T,prob=p)))
P <- sum(X<x)/length(X)    # probability that X < x

par(mfrow=c(1,2))
hist(X)
plot(quantile(X,probs=seq(0,1,.01)),seq(0,1,.01),type="l",xlab="x",ylab="P(X < x)")
lines(c(x,x,0),c(0,P,P),col="red",lty=2)

这是有道理的,因为预期的一面

E(s) = 1*0.1 + 2*0.1 + 3*0.1 + 4*0.1 + 5*0.3 + 6*0.3 = 4.3

由于您要模拟 50 次滚动,因此总数的期望值应该是 50*4.3,或大约 215,这几乎就是它的值。

下面的慢步在我的系统上运行大约 3.5 秒。显然实际时间将取决于模拟中的试验次数和计算机的速度,但 5 分钟是荒谬的......

system.time(X <- sapply(1:k,function(i)sum(sample(1:6,n,replace=T,prob=p))))
#    user  system elapsed 
#    3.20    0.00    3.24 
于 2014-05-05T04:49:54.620 回答