说在前面

今天在知乎上面看到了一个有趣的问题,就开始颓废了(最后一次颓废)

来源于知乎,随机分配钱求财富分布

问题描述:

房间内有 100 人,每人有 100 块,每分钟随机给另一个人 1 块,最后这个房间内的财富分布怎样?

链接:来自知乎

刚刚开始拿到这个题目的时候,我想,既然是随机的,那么就一定会分配均匀了啊。然而并不是我想的这样,在提问者给出来的代码跑出来的数据中,情况确实恰恰相反,随着数据的范围不断的扩大,反而贫富差距越来越大了。

实验操作

然后就自己尝试着跑了一下代码,一个很垃圾的C++代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cctype>
using namespace std;
long long a[200],n,num,m,b[200],sum;
int main()
{
//freopen("a.out","w",stdout);
cin>>n; m=n;
for(int i=0;i<=20;i++) a[i]=100;
while(n-->0)
{
int This=rand()%20;
if(a[This]) a[This]--;
else {
n++;
continue;
}
int That=rand()%20; a[That]++;
if(++num==m/10)
{
sum++;
num=false;
cout<<"Data ";
for(int i=0;i<20;i++)
cout<<a[i]<<' ';
cout<<endl;
}
}
sort(a,a+20);
cout<<"Sort ";
for(int i=0;i<20;i++)
cout<<a[i]<<' ';
cout<<endl;
return 0;
}

测试结果

然后开始逐渐的扩大范围:

1.当进行分配10次的时候,最后贫富差距进行排序:

Sort 97 99 99 99 100 100 100 100 100 100 100 100 100 100 100 101 101 101 101 102

可以看到并没有什么过大的差距。

2.当进行分配100次的时候,最后贫富差距进行排序:

Sort 95 96 97 97 98 98 98 99 100 100 100 101 101 101 102 103 103 103 103 105

这组数据仍然看不出来有什么差距。

3.当进行分配1000次的时候,最后贫富差距进行排序:

Sort 81 81 84 89 93 94 94 96 102 104 106 106 106 107 107 108 108 110 112 112

这个时候已经有些大了

4.当进行分配10000次的时候,最后贫富差距进行排序:

Sort 54 55 59 61 67 79 84 85 85 93 97 98 103 114 127 137 147 148 149 158

这个时候已经是非常非常的明显了。

5.当进行分配100000次的时候,最后贫富差距进行排序:

Sort 6 22 28 29 30 54 59 80 83 94 95 107 122 144 151 156 173 175 190 202

这个时候贫富差距已经非常的可观了,然而继续。

6.当进行分配10000000次的时候,最后贫富差距进行排序:

Sort 4 6 11 12 14 14 24 44 47 57 57 63 77 81 81 151 197 326 342 392

继续扩大。

7.当进行分配100000000次的时候,最后贫富差距进行排序:

Sort 1 11 15 22 36 40 46 46 58 69 76 90 96 124 132 195 211 225 233 274

当实验进行到了这一步的时候,足够大的基数足以证明随着计算次数不断的增加,最后拿到钱的数目差距会越来越大。

继续分析

一个人的钱是从头到尾都是一直少或者一直多吗?由于采用的是随机数据,所以说应该不会是一直保持这样的。于是在中间的计算过程中,我们将每个数据曾经的最大值和最小值也一起计算出来(稍微修改一下代码):

当知己进行分配100000000次的时候:

  • Fanily 36 233 195 124 69 76 211 1 274 90 132 15 46 46 225 58 96 11 22 40

  • Max 429 762 508 706 587 687 576 594 682 661 707 568 744 676 532 523 802 480 702 762

  • Min 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

由于最小值不好看出来,所以说就修改一下代码,允许有负债的情况。

  • Final 2229 860 -572 -252 996 -1845 -4223 -125 -2361 -1549 -2366 1596 970 -2503 4414 1333 -1326 5568 3196 -2040

  • Max 4058 2265 1767 3389 3088 1275 1358 1106 561 2911 2748 4362 2909 606 4689 1967 1079 5978 3522 483

  • Min -812 -1925 -1893 -433 -1054 -2174 -4467 -3407 -4375 -2584 -2548 -665 -1232 -3983 -1269 -2084 -2403 -1087 -522 -3753

越来越有意思了,虽然有一些曾经咸鱼,最大值却非常大的,但是可以看到,整体上是呈现线性排布的,也就是说,结果小的一般最小值就小,最大值就不大……

分析结论

我为了保证随机数的准确性,特意跑了一遍随机数,发现在大基数的条件下,每个数被选择到的概率是相等的,但是频率并不相等(好像是废话),数据如下(数据为这个数被选中的次数):

Rand: 5001361 5004661 5005396 5000955 5001247 5002474 5001408 4998552 5001943 4995260 4998057 5001047 4999649 4996001 4997516 5000693 4996266 5002321 4998128 4999065

等等,好像问题件就是出现在了这里啊……这里表示的是选中这个当前这个人来扣掉他一块钱,然后分给其他人。那么在这个大的样本里面,选中的误差值大概在±9000以内。问题就是出在了±9000以内。

也就是说,计算机里的随机数选择的时候,在进行100000000选择的时候,误差值是在±9000以内。那么会不是正是因为这9000的误差值,导致的贫富差距呢?

毕竟我们看到,如果允许负债的话,和100的差值大约在±5000内。这是不是因为计算机随机数并不“随机”的原因导致的呢?所以说这个问题可能就是因为计算机的随机数的误差导致的贫富差距。因为误差比较小,所以只有在进行1000000000次选择的时候,所体现出来的误差的范围扩大到了±9000,那么贫富差距可能就是由于这些误差才显示出来的。

  • 其实这里导致误差看起来如此之大的原因其实很简单,虽然随机数的误差并不大,但是由于基数很小(20或者100),在每个人身上的误差就会累加起来,虽然制造成了大概一百元左右的误差,但是看起来却是非常大的。

  • 如果我们将每个人有100元变成每个人有1000000000元,相信你看到的答案又不一样了。

  • emmmm 事实上出现这种情况我的看法是因为误差(方差)的积累加上基数很小的方法造成的。仅仅作为一个参考放在这里。