崩坏3精准补给池抽卡模拟,求数学期望及一些相关概率

简单的模拟,记录一下结果。

没有编写10连保底的机制。因为官方公示的概率已经把保底的机制算上了,所以不写也完全不影响求期望。不过这会使很欧和很非的人的比例同时增大,不过差的不大(大概)。 或者说,同概率下,十连保底机制对欧洲人不友好,对亚洲非洲人稍友好。

1.不考虑使用许愿池的情况

	static boolean checkFlags(boolean[] flags) {
		for (int i = 0; i < flags.length; i++)
			if (flags[i] == false)
				return false;
		return true;
	}

	public static void main(String[] args) {
		double average = 0;
		long countOfLottery = 0;
		int numberOfTestPeople = 100000;
		int[] boundOfLottery = new int[] { 10, 40, 93, // 648*4
				130, 150, 185 // 648*8
		};
		int[] numberOfLessThanBound = new int[boundOfLottery.length];
		int minCount = 30000;
		int maxCount = -1;
		double rate = 0.015;
		double[] rates = { 2.479, 1.24, 1.24, 1.24 };// 百分比
		double[] rates2 = new double[rates.length + 1];
		boolean[] flags = new boolean[rates.length];

		double sum = 0;
		for (int i = 0; i < rates.length; i++) {
			rates2[i] = sum;
			sum += rates[i];
		}
		rates2[rates2.length - 1] = sum;

		for (int i = 0; i < numberOfTestPeople; i++) {
			int count2 = 0;
			for (int j = 0; j < rates.length; j++) {
				flags[j] = false;
			}
			do {
				countOfLottery++;
				count2++;
				double temp = Math.random() * 100;
				for (int j = 0; j < rates.length; j++) {
					if (rates2[j] <= temp & temp < rates2[j + 1])
						flags[j] = true;
				}
			} while (!checkFlags(flags));
			if (maxCount < count2)
				maxCount = count2;
			if (minCount > count2)
				minCount = count2;
			for (int j = 0; j < boundOfLottery.length; j++)
				if (count2 <= boundOfLottery[j])
					numberOfLessThanBound[j]++;
		}
		average = (double) countOfLottery / (double) numberOfTestPeople;
		System.out.println("模拟十万人抽卡");
		System.out.println("每个人当其抽齐up的武器以及一套圣痕时就停止抽卡");
		System.out.println("平均抽卡次数: " + String.format("%8.2f", average));
		System.out.println("最大抽卡次数: " + String.format("%8d", maxCount));
		System.out.println("最小抽卡次数: " + String.format("%8d", minCount));
		for (int i = 0; i < boundOfLottery.length; i++)
			System.out.println("抽卡次数<=" + String.format("%3d", boundOfLottery[i]) + " 的概率:"
					+ String.format("%8.2f",
							(double) numberOfLessThanBound[i] * 100 / (double) numberOfTestPeople)
					+ "%");
	}

执行结果:

模拟十万人抽卡
每个人当其抽齐up的武器以及一套圣痕时就停止抽卡
平均抽卡次数:   151.89
最大抽卡次数:     1019
最小抽卡次数:        6
抽卡次数<= 10 的概率:    0.02%
抽卡次数<= 40 的概率:    3.60%
抽卡次数<= 93 的概率:   28.90%
抽卡次数<=130 的概率:   49.43%
抽卡次数<=150 的概率:   58.91%
抽卡次数<=185 的概率:   72.23%

2.考虑使用许愿池的情况

	static boolean QiYuan(int b, int c, int d) {
		if (d > 0)
			return false;
		if (b > 0 && c > 0)
			if (b + c >= 4)
				return true;
		return false;
	}

	public static void main(String[] args) {
		double average = 0;
		long countOfLottery = 0;
		int numberOfTestPeople = 100000;
		int[] boundOfLottery = new int[] { 10, 40, 93, // 648*4
				130, 150, 185 // 648*8
		};
		int[] numberOfLessThanBound = new int[boundOfLottery.length];
		int minCount = 30000;
		int maxCount = -1;
		double rate = 0.015;
		double rate1 = 2.479, rate2 = 1.24, rate3 = 1.24, rate4 = 1.24;
		for (int i = 0; i < numberOfTestPeople; i++) {
			int count2 = 0;
			int a = 0, b = 0, c = 0, d = 0;
			do {
				countOfLottery++;
				count2++;
				double temp = Math.random() * 100;
				if (temp < rate1 & 0 <= temp)
					a++;
				else if (temp < rate1 + rate2 & rate1 <= temp)
					b++;
				else if (temp < rate1 + 2 * rate2 & rate1 + rate2 <= temp)
					c++;
				else if (temp < rate1 + 3 * rate2 & rate1 + 2 * rate2 <= temp)
					d++;
				if (QiYuan(b, c, d) || QiYuan(b, d, c) || QiYuan(c, d, b))
					break;

			} while (a == 0 || b == 0 || c == 0 || d == 0);
			if (maxCount < count2)
				maxCount = count2;
			if (minCount > count2)
				minCount = count2;
			for (int j = 0; j < boundOfLottery.length; j++)
				if (count2 <= boundOfLottery[j])
					numberOfLessThanBound[j]++;
		}
		average = (double) countOfLottery / (double) numberOfTestPeople;
		System.out.println("模拟十万人抽卡");
		System.out.println("每个人当其抽齐up的武器以及一套圣痕时就停止抽卡");
		System.out.println("平均抽卡次数: " + String.format("%8.2f", average));
		System.out.println("最大抽卡次数: " + String.format("%8d", maxCount));
		System.out.println("最小抽卡次数: " + String.format("%8d", minCount));
		for (int i = 0; i < boundOfLottery.length; i++)
			System.out.println("抽卡次数<=" + String.format("%3d", boundOfLottery[i]) + " 的概率:"
					+ String.format("%8.2f",
							(double) numberOfLessThanBound[i] * 100 / (double) numberOfTestPeople)
					+ "%");
	}

执行结果:

模拟十万人抽卡
每个人当其抽齐up的武器以及一套圣痕时就停止抽卡
平均抽卡次数:   106.05
最大抽卡次数:      596
最小抽卡次数:        5
抽卡次数<= 10 的概率:    0.04%
抽卡次数<= 40 的概率:    6.56%
抽卡次数<= 93 的概率:   47.11%
抽卡次数<=130 的概率:   72.75%
抽卡次数<=150 的概率:   81.96%
抽卡次数<=185 的概率:   91.81%

 

你可能感兴趣的:(Java,java,崩坏3,抽卡,概率)