前言
在閱讀了文章擁有多個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;
}
}