理解文章《擁有多個A的概率:又一個條件概率悖論》中的一個看似奇怪的現象

前言

在閱讀了文章擁有多個A的概率:又一個條件概率悖論 以後,覺得很難理解,於是就做了一個簡單的實驗,終於理解了其中的原因。

問題

Q1. 四個人打橋牌。其中一個人說,我手上有一個A。請問他手上有不止一個A的概率是多少?
Q2. 四個人打橋牌。其中一個人說,我手上有一個黑桃A。請問他手上有不止一個A的概率是多少?

根據條件概率計算:

Q1 概率爲(C(52,13) – C(48,13) – C(48,12) * 4) / (C(52,13) – C(48,13)) = 5359/14498 ≈ 37%。
Q2 的概率爲(C(51,12) – C(48,12)) / C(51,12) = 11686/20825 ≈ 56%

所以根據以上的結論,如果這個人宣佈了手中A的花色,那麼他手中有一個以上A的概率竟然會大大增加。

驗證

爲了驗證這個結論,我也做了相關測試,Java代碼見文章最後。發現結論確實是正確的。爲了進一步分析,我還追加了以下數據:

  • x1:有1個A的概率;
  • y1:有2張A的概率;
  • x2: 有1個黑桃A的概率;
  • y2: 有1個黑桃A且其他至少還有1張A的概率 。

結果如下所示:

x1 = 0.7131, y1 = 0.2761, y1/x1 = 0.3872.
x2 = 0.2554, y2 = 0.1490, y2/x2 = 0.5832.

結論

從這個結果來看,“如果這個人宣佈了手中A的花色,那麼他手中有一個以上A的概率竟然會大大增加” 這個說法倒沒錯,而且也並不難理解。根本原因就是明確了花色以後,降低了不確定性,從而提高了有多張A的概率。這個說話有點抽象,可以從數據解釋。

對比數據可以發現 ,x1到x2下降爲原來的約1/3,而且y1至y2下降爲原來的約1/2,所以確定以後,x的總結合數量下降速度快於y的下降速度,所以我們可以得出一個結論:通過增加確定性,可以提高對事件的預測的概率。也就是說確定了A的花色,實際上是降低了A的可能組合的情況,所以有多一張A的機率確實是增加的。因此,在任何的系統中,只要不確定性被降低,我們預測的準確性就會增加。

源代碼

import java.util.Random;

public class ProbilityTest{
	static Random rand = new Random();

	public static void main(String[] args) {
		int x1 = 0, y1 = 0, x2 = 0, y2 = 0, total = 100000;
		for (int i = 0; i < total; i++) {
			int[] sample = randomSubset(52, 13);
			if (count(sample, 1, 2, 3, 4) > 0) x1++;
			if (count(sample, 1, 2, 3, 4) > 1) y1++;
			if (count(sample, 1) > 0) x2++;
			if (count(sample, 1) > 0 && count(sample, 2, 3, 4) > 0)	y2++;
		}
		System.out.printf("x1 = %.4f, y1 = %.4f, y1/x1 = %.4f.\n", 1.0 * x1 / total, 1.0 * y1 / total, 1.0 * y1 / x1);
		System.out.printf("x2 = %.4f, y2 = %.4f, y2/x2 = %.4f.\n", 1.0 * x2 / total, 1.0 * y2 / total, 1.0 * y2 / x2);
	}

	/**
	 * Count the number of elements that are contained in set.
	 * @param set
	 * @param values
	 * @return
	 */
	private static int count(int[] set, int... values) {
		int count = 0;
		for (int v : values)
			if (contains(set, v))
				count++;
		return count;
	}

	
	/**
	 * Whether v is contained in set.
	 * @param set A set.
	 * @param v A value.
	 * @return
	 */
	private static boolean contains(int[] set, int v) {
		if (set == null || set.length == 0)
			return false;

		for (int s : set)
			if (s == v)
				return true;

		return false;
	}

	/**
	 * Get a subset from a randomized set.
	 * @param setSize the size of set.
	 * @param subsetSize the size of subset.
	 * @return
	 */
	static int[] randomSubset(int setSize, int subsetSize) {
		int[] all = new int[setSize];
		for (int i = 0; i < all.length; i++)
			all[i] = i;

		for (int i = 0; i < all.length; i++) {
			int p = rand.nextInt(all.length);
			int t = all[i];
			all[i] = all[p];
			all[p] = t;
		}

		int[] sample = new int[subsetSize];
		for (int i = 0; i < sample.length; i++)
			sample[i] = all[i];

		return sample;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章