本文的网课内容学习自B站左程云老师的算法详解课程,旨在对其中的知识进行整理和分享~
一.实验:
1.题目:
一开始有100个人,每个人都有100元,在每一轮都做如下的事情:
1.每个人都必须拿出1元钱给除自己以外的其他人,给谁完全随机
2.如果某个人在这一轮的钱数为0,那么他可以不给,但是可以接收
那么发生很多很多轮之后,这100个人的社会财富分布的会均匀吗?
2.分析:
1.基尼系数:
用于判断一个社会的贫富差距,基尼系数越小,代表社会财富分布越均衡;越大则代表财富分布越不均衡。
2.基尼系数计算公式:
3.代码实现
package experiment;
import java.util.Arrays;
public class ExperimentDemo {
public static void main(String[] args) {
System.out.println("一个社会的基尼系数是一个在0~1之间的小数");
System.out.println("基尼系数为0代表所有人的财富完全一样");
System.out.println("基尼系数为1代表有一个人掌握了全社会的财富");
System.out.println("基尼系数越小,代表社会财富分布越均衡;越大则代表财富分布越不均衡");
System.out.println("在2020年,世界各国的平均基尼系数为0.44");
System.out.println("目前普遍认为,当基尼系数到达 0.5 时,就意味着社会贫富差距非常大,分布非常不均匀");
System.out.println("社会可能会因此陷入危机,比如大量的犯罪或者经历社会动荡");
System.out.println("测试开始");
int n = 100;//人数
int t = 1000000;//轮数
System.out.println("人数 :" + n);
System.out.println("轮数 :" + t);
experiment(n, t);
System.out.println("测试结束");
}
//实验
public static void experiment(int n, int t) {
double[] wealth = new double[n];//用一个数组wealth来记录每个人的财富
Arrays.fill(wealth, 100);//初始时,每个人的财富都是100
boolean[] hasMoney = new boolean[n];//判断一个人是否有钱
for (int i = 0; i < t; i++) {
//每一轮先判断每个人是否有钱
Arrays.fill(hasMoney, false);//初始化是假设所有人都没有钱
for (int j = 0; j < n; j++) {
if (wealth[j] > 0) {
hasMoney[j] = true;//如果有钱就将该下标的数组值改成true
}
}
for (int j = 0; j < n; j++) {
//如果这个人有钱,就将这个人的1块钱随机给另一个人
if (hasMoney[j]) {
int other = j;//被给钱的人的编号,先将它初始化为自己
//如果被给钱的人是给钱的人自己,那么就在0 ~ n-1随机一个编号,直到这个编号的人不是自己
do {
//(int) (Math.random() * n);
//表示生成一个0 ~ n -1的等概率随机整数
other = (int) (Math.random() * n);
} while (other == j);
wealth[j]--;//给钱人的财富减一
wealth[other]++;//被给钱的人财富加一
}
}
}
//对财富多少进行排序,打印每个人的财富
Arrays.sort(wealth);
System.out.println("列出每个人的财富(从贫穷到富有)");
for (int i = 0; i < wealth.length; i++) {
System.out.print((int) wealth[i] + " ");
if (i % 10 == 9) {
System.out.println();
}
}
System.out.println();
System.out.println("这个社会的基尼系数为:" + calculateGini(wealth));
}
//计算基尼系数
public static double calculateGini(double[] wealth) {
double sumOfAbsoluteDifferences = 0;//每个人财富差值的绝对值的总和
double sumOfWealth = 0;
for (int i = 0; i < wealth.length; i++) {
//遍历记录每个人财富的数组,计算sumOfWealth
sumOfWealth += wealth[i];
for (int j = 0; j < wealth.length; j++) {
//计算sumOfAbsoluteDifferences
sumOfAbsoluteDifferences += Math.abs(wealth[i] - wealth[j]);//下标i位置的财富与下标为j位置的财富差值的绝对值
}
}
return sumOfAbsoluteDifferences / (2 * wealth.length * sumOfWealth);//基尼系数表达式
}
}