學以致用——Java原始碼——任意次拋雙骰結果模擬程式(Dice Rolling, updated in 2018)
本程式基於2年前的程式做了以下改進:
1. 2018年12月25日優化:使用陣列元素作為計數器 (而不是用switch...case或if...else進行逐個判斷)
2. 修改了概率計算的一個bug (顯示小數點位數為兩位,只需要格式化輸出即可)
程式碼如下:
package exercises.ch7Arrays; //Java how to program, 10th/e, Exercise 7.17-Dice Rolling /**(Dice Rolling) Write an application to simulate the rolling of two dice. The application should use an object of class Random once to roll the first die and again to roll the second die. The sum of the two values should then be calculated. Each die can show an integer value from 1 to 6, so the sum of the values will vary from 2 to 12, with 7 being the most frequent sum, and 2 and 12 the least frequent. Figure 7.28 shows the 36 possible combinations of the two dice. Your application should roll the dice 36,000,000 times. Use a one-dimensional array to tally the number of times each possible sum appears. Display the results in tabular format.*/ import java.util.Scanner; public class RollingDice2018 { public static int rollDice() { int dice1=(int)(1+Math.random()*6); int dice2=(int)(1+Math.random()*6); return dice1+dice2; } public static void main(String[] args){ int size=0; Scanner input=new Scanner(System.in); do{ System.out.print("請輸入拋雙骰的次數(輸入-1退出):"); size=input.nextInt(); if(size==-1){ System.out.printf("已退出程式"); break; } int rollingResult=0; int[] frequency=new int[13]; double[] possibility=new double[13]; double possibilityTotal=0.0; double percentTotal=0.0; int totalRolling=0; System.out.println("拋雙骰開始:"); for (int i=0;i<size;i++){ rollingResult=rollDice(); ++frequency[rollingResult]; //2018年12月25日優化:使用陣列元素作為計數器 } System.out.println("拋雙骰結束:"); for (int i=2;i<13;i++){ possibility[i]=(double)frequency[i]/size; } System.out.printf("已模擬拋雙骰共%d次,統計結果如下:\n",size); System.out.println("拋雙骰點數合計\t丟擲次數\t\t所佔百分比:"); for (int i=2;i<13;i++){ //百分比取兩位小數推演過程:0.12545->1254.5+0.5=1255/10000=0.1255*100 System.out.printf("%d\t\t%d\t\t%.2f%%%n",i,frequency[i],(double)(possibility[i]*10000)/100); //System.out.print("%"+"\n"); } for(double p:possibility){ possibilityTotal+=p; percentTotal+=(p*10000)/100; } for(int f:frequency) totalRolling+=f; System.out.printf("校驗值-丟擲次數合計:%d,概率合計:%.2f,百分比合計:%.2f\n\n\n",totalRolling,possibilityTotal,percentTotal); }while(size!=-1); input.close(); } }
執行結果:
請輸入拋雙骰的次數(輸入-1退出):10 拋雙骰開始: 拋雙骰結束: 已模擬拋雙骰共10次,統計結果如下: 拋雙骰點數合計 丟擲次數 所佔百分比: 2 0 0.00% 3 0 0.00% 4 0 0.00% 5 2 20.00% 6 1 10.00% 7 1 10.00% 8 0 0.00% 9 1 10.00% 10 5 50.00% 11 0 0.00% 12 0 0.00% 校驗值-丟擲次數合計:10,概率合計:1.00,百分比合計:100.00
請輸入拋雙骰的次數(輸入-1退出):1000 拋雙骰開始: 拋雙骰結束: 已模擬拋雙骰共1000次,統計結果如下: 拋雙骰點數合計 丟擲次數 所佔百分比: 2 23 2.30% 3 68 6.80% 4 77 7.70% 5 106 10.60% 6 131 13.10% 7 177 17.70% 8 128 12.80% 9 116 11.60% 10 81 8.10% 11 71 7.10% 12 22 2.20% 校驗值-丟擲次數合計:1000,概率合計:1.00,百分比合計:100.00
請輸入拋雙骰的次數(輸入-1退出):10000 拋雙骰開始: 拋雙骰結束: 已模擬拋雙骰共10000次,統計結果如下: 拋雙骰點數合計 丟擲次數 所佔百分比: 2 263 2.63% 3 554 5.54% 4 804 8.04% 5 1191 11.91% 6 1399 13.99% 7 1647 16.47% 8 1329 13.29% 9 1128 11.28% 10 866 8.66% 11 548 5.48% 12 271 2.71% 校驗值-丟擲次數合計:10000,概率合計:1.00,百分比合計:100.00
請輸入拋雙骰的次數(輸入-1退出):1000000 拋雙骰開始: 拋雙骰結束: 已模擬拋雙骰共1000000次,統計結果如下: 拋雙骰點數合計 丟擲次數 所佔百分比: 2 27926 2.79% 3 55949 5.59% 4 83441 8.34% 5 111135 11.11% 6 138894 13.89% 7 165858 16.59% 8 139348 13.93% 9 110583 11.06% 10 83645 8.36% 11 55509 5.55% 12 27712 2.77% 校驗值-丟擲次數合計:1000000,概率合計:1.00,百分比合計:100.00
請輸入拋雙骰的次數(輸入-1退出):36000000 拋雙骰開始: |
彩蛋:
這個程式可以用來演示大數定律(Law of Large Number),由程式執行結果來看,當丟擲1000000次後,模擬結果與理論概率高度吻合(這也等於是驗證了程式的準確性)。
參考文章:
1. 學以致用-擲雙骰兒(craps)遊戲的直方圖(概率分佈)資料分析,https://blog.csdn.net/hpdlzu80100/article/details/78920409
2. 經典問題-搖雙色模擬(次數自定義)(Dice Rolling),https://blog.csdn.net/hpdlzu80100/article/details/51852730