博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一道数学题的思考
阅读量:6892 次
发布时间:2019-06-27

本文共 4617 字,大约阅读时间需要 15 分钟。

  最近看见一道数学题,比较有意思:

房间里有100个人,每人都有100元钱,他们在玩一个游戏。每轮游戏中,每个人都要拿出一元钱随机给另一个人,最后这100个人的财富分布是怎样的?我们不妨把这场游戏视作社会财富分配的简化模型,从而模拟这个世界的运行规律。我们假设:每个人在18岁带着100元的初始资金开始玩游戏,每天玩一次,一直玩到65岁退休。“每天拿出一元钱”可理解为基本的日常消费,“获得财富的概率随机”是为了……嗯……简化模型。以此计算,人一生要玩17000次游戏,即获得17000次财富分配的机会。答案有如下三种情况:

  当看见这道题的时候,我认为财富的分布应该是接近均匀分布,毕竟概率是均等的。但是答案竟然是接近冥律分布,为什么呢?我决定使用代码来计算一遍!

  使用代码计算,首先考虑一个问题,就是随机数,目前 Random 函数的随机数存在“伪随机”,就是每次的随机数都是一样的,我们可以通过代码来测试一下:

import java.util.Random;public class MyClass {    public static void main(String[] args) {               for (int i = 0; i < 3; i++) {            System.out.println( "第"+i+"次输出结果"+new Random(5).nextInt(100));        }    }}复制代码

接下来看看日志结果,大家就明白了!

第0次输出结果87第1次输出结果87第2次输出结果87第3次输出结果87第4次输出结果87第5次输出结果87第6次输出结果87第7次输出结果87第8次输出结果87第9次输出结果87复制代码

避免随机数的方法比较多,有减掉种子参数()、将 Random 对象生成一个对象,每次使用同一个对象,代码验证一下:

import java.util.Random;public class MyClass {    public static void main(String[] args) {        Random rl = new Random();        for (int i = 0; i < 10; i++) {            System.out.println( "无种子参数第"+i+"次输出结果"+ new Random().nextInt(10));            System.out.println( "同 Random 对象第"+i+"次输出结果"+ rl.nextInt(10));        }    }}复制代码

日志验证结果:

无种子参数第0次输出结果4同 Random 对象第0次输出结果6无种子参数第1次输出结果0同 Random 对象第1次输出结果1无种子参数第2次输出结果8同 Random 对象第2次输出结果8无种子参数第3次输出结果4同 Random 对象第3次输出结果4无种子参数第4次输出结果1同 Random 对象第4次输出结果8无种子参数第5次输出结果7同 Random 对象第5次输出结果6无种子参数第6次输出结果8同 Random 对象第6次输出结果4无种子参数第7次输出结果8同 Random 对象第7次输出结果2无种子参数第8次输出结果7同 Random 对象第8次输出结果8无种子参数第9次输出结果0同 Random 对象第9次输出结果1复制代码

上述的“伪函数”的原因是种子参数的使用——

在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。因此,相同种子数的Random对象,相同次数生成的随机数字是完全相同的。

  了解了Random对象以后,接下来需要实现财富分配的过程,上面说的是规则不大清晰,只说了每个人的初始资金为100元,每次中奖了就分配,然后总次数为17000次。我们在实现的过程中需要考虑的问题还有几点:

  1. for 循环的时候,是 100 个人每次抽奖 17000 次,还是抽 17000 次奖,每次遍历 100 个人?
  2. 当每个人的资金减少到0元以后是否还有机会中奖?
  3. 当有人的资金减少为 0 时,可分配的奖金响应减少,如何纪录?
  4. 当问题 1 为否定时,会发生无人中奖的情况,这个时候已经出资1元的资金需要取回,且总次数是否增加?

  第一、虽然总的计算次数都是1700000次,但是这里的逻辑不一样,前者抽奖次数达到了1700000次,后者抽奖次数固定为17000次,按照逻辑判断,应该选后者。

  第二、我将这个问题理解为博弈,并非作者所提的社会问题(社会问题需要考虑到财富平均的财富再分配,博弈考虑的是我付出了有多大的收益),因此第一个问题我的答案是没有机会中奖,这样也会更加公平!

  第三、我的做法是在每轮博弈前设置一个奖金初始值 bonus,假设每次一开始都不知道有人需要退出,因此初始值一直是100元,接下来在每次收取博弈奖金的时候判断参与者是否还有资金(资金是否为 0 或者为 -1)参与本轮博弈,没有的话我会给他们一个标记(资金设为 -1),并且将奖金 bonus 减去 1 。当 100 人循环完毕以后,博弈奖金就是 bonus 了!

  第四、该问题类似第二个问题,在每轮博弈前设置一个标记 isBouns ,定义为无人中奖。然后在得到 bonus 以后,就可以开奖了。如果遇到无人中奖(假设中奖号为 99 ,但是 99 号没有投注博弈资金了,则本轮无人中奖),这个时候可以通过判断 isBouns 来决定总次数是否增加。由于总次数 17000 次是来自时间的计算,所以这里我也没有增加总次数了。如果需要增加,我们可以对总次数定义一个变量 22K (可以自行百度22k 这个故事),初始值为 17000 ,在无人中奖的时候加 1 即可。

代码如下:

import com.google.gson.Gson;import java.util.ArrayList;import java.util.List;import java.util.Random;/** * Created by κ?? on 2017/7/30. */public class Test {    static List
data = new ArrayList<>(); public static void main(String []args) { Random rl = new Random(); int count = 100; int all = 17000; for (int i = 0; i < 100; i++) { data.add(100); } int ran = rl.nextInt(100); for (int i = 0; i < 17000; i++) { boolean isBouns = false; int bonus = 100; for (int j = 0; j < 100; j++) { if(data.get(j) == 0){ data.set(j,-1); bonus--; }else if(data.get(j) != -1){ int value = data.get(j); data.set(j,value-1); }else{ bonus--; } } if(data.get(ran)!=-1){ int value = data.get(ran); data.set(ran,value+bonus); isBouns = true; } ran = rl.nextInt(100); if(!isBouns){ for (int j = 0; j < 100; j++) { int value = data.get(j); if(value!=-1){ data.set(j,value+1); } } } } System.out.println(getData()); //数据详情 System.out.println(new Gson().toJson(data)); } private static int getData() { int result = 0; int count = 0; int winer = 0; for (int i = 0; i < 100; i++) { if(data.get(i) != -1 && data.get(i) != 0){ result+=data.get(i); count++; //绝对赢家 if(data.get(i)>100){ winer++; } } } System.out.println("共有"+winer+"人赢了!其中有"+count+"还有钱!"); //总资金 10000,检查这个值计算是否有计算出错 return result; }}复制代码

  最后说一下我的计算结果:

  代码运行10 次,累计208人还有钱,其中7人不足100元,也就是说平均每轮(几十年的概念)有20.8%的概率还有能力继续博弈,每轮有20.1%的概率盈利!


参考文章:


文章来源

转载于:https://juejin.im/post/5c8fb15ee51d456f60502122

你可能感兴趣的文章
illustrate ARC with graphs
查看>>
版本管理 - Git
查看>>
待看东西
查看>>
创建和使用RMAN存储脚本
查看>>
杂七杂八的文档资料。
查看>>
C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 访问频率限制功能实现、防止黑客扫描、防止恶意刷屏...
查看>>
eclipse中项目右上方有一个s,eclipse中项目左下方友谊个红色的叉,eclipse中项目左下方友谊个红色的感叹号...
查看>>
gis数据格式转换(数据导入)ConvertFeaCls
查看>>
启发式算法(Heuristic Algorithm)
查看>>
李洪强iOS学习交流群-iOS大神群
查看>>
Netty权威指南之NIO通信模型
查看>>
Java静态分派与动态分派(二)
查看>>
How to: Set Tomato Firmware for Wireless Client Modes
查看>>
Eclipse上GIT插件EGIT使用手册之八_解决推送冲突
查看>>
CSS 技巧
查看>>
【剑指Offer学习】【面试题19 :二叉树的镜像】
查看>>
NTFS会对游戏运行有不良影响吗?
查看>>
初识C++继承
查看>>
怎么和公司谈出合理的期权激励?
查看>>
产品经理如何进行产品数据分析?
查看>>