每两个月一次的“二姨妈”

偶数月的26号中午11点到下午1点,沙漠君的手机上就会收到一条短信,不是中介和广告,但内容肯定是一样的:“很遗憾,该编码本次摇号未中签或摇号资格已过期”。二姨妈真是比大姨妈都准时!呵呵!

几年过去了,在帝都辛苦挤地铁的你,是否和沙漠君有同样的疑问?

  • 现在摇号到底有多难?
  • 哪些人摇到了号?平均摇了几回?
  • 有没有提升摇号概率的方法?
  • 摇号算法是什么?是绝对公平的吗?

沙漠君用真实的数据,告诉你答案。

摇到号的概率是多少?

2016到2017年,北京每年各有15万个小汽车指标。新能源比例达到40%,普通号只剩9万个,一年6次,每次15000个。

但是!2016年第3次摇号,摇号池总数量是9917981!总摇号人数270.7万!如果你摇号次数在24次之内,那么本次摇到的概率为千分之一! 花166年摇一千次都不中的概率是37%!

每摇12次没中签,真的会像官方的说法,可能性增加一倍么?太天真!因为你增加,别人的也在增加。除非你是第一批参加摇号的人,否则会有更多的人比你增加更高的概率。因此,号是越来越难摇的。

五年间,摇到号的人数总共94万人。2011年时,每隔10个人就会有一个幸运儿,几年前买车确实比现在买车容易太多。看看这张图:

2012年和2014年算是摇号黄金期,每期都有接近两万人摇到号,可是到了2016年,这个数字降为1.3万。然而,下面这张图绝对让你哭晕!

当然,每年增加的摇号人数基本是线性的:

从第一期的18万,到2016年6月份的270万,每年增加五十万人。我们难以确定新增加的是哪些人数,按照政策,学生可能占了相当大的比重(可参考附录)。

那么,那些摇到号的人,总共摇了多少次呢?下面这张图回答你:

有接近九万人第一次就摇到号了,还有190人摇了整整51次才拿到号,这个曲线非常地光滑,几个凸起点正好是调整中签率的门限,非常符合数学的美感。

有14201人,51次摇号没有一次成功。真正的幸运儿是这些人:在最近的这一期,以1/1000的概率第一次抽签就拿到了号,一共90人。

摇号程序是否公平?

作为程序员的沙漠君,被激发了昂扬的斗志,我们来验证一下摇号程序是否公平。

通过使用沙漠君自己开发的Hawk爬虫程序(见备注),采集了从2011年到2016年51期每期的摇号池列表和随机种子。同时,我还下载了它的摇号程序,用于分析其摇号算法。程序使用C#编写,沙漠君破解它的源代码简直不要太容易。

为了能让不懂程序的读者也能理解,我用尽量简明的语言描述其摇号方法:假设有5人摇号,每个人都有唯一的ID,1-5,用户2,4有两倍中签率,用户3有3倍中签率,那么摇号池排列如下:

  • 第一轮,把所有人都按次序排列,即上面的序号1-5;
  • 第二轮,把所有中签率大于等于2倍的按次序排列,即上面的6-8
  • 第三轮,把大于等于三倍的按次序排列,上面只有9

现要求从池中随机抽取三个序号。计算机能通过一个种子,可以生成一串看似随机的伪随机序列。在一般程序中,种子通常是当前运行的时间。因每次运行时间不同,所以结果也不一同。

而摇号程序有趣的地方就在这里,种子是事先提供好的一串6位数字,一旦你知道它,那么你在摇号前就能预测哪些人被抽中。每个人的中签倍率和ID都是确定的,因此分析6位的随机数种子是如何产生的,成了解决问题的关键。

6位随机种子是如何产生的?

沙漠君研究了首都之窗上用于公示随机数的2013年某期的视频。

公证人员事先从市民中选出12位代表人。主持人在鱼缸中随机抽出6个球,每个球都是一个市民代表人的号码。之后,6个代表人会依次敲击键盘,随机产生出0-9的随机数作为随机数种子。有趣的地方就在这里!!

主持人说,请每一位代表摇出号码,我一帧帧地分析了视频,从市民代表在键盘上的操作位置来猜测,点击的多半是是回车键,但代表按键盘都是背对摄影机的。你可以简单理解为,每按一次回车,电脑产生出一个新的0-9的数字,总计6个。

网站提供了随机产生摇号号码的程序,却没有提供随机产生六位种子的程序。这个随机数种子本身,会不会事先保存,一定能保证随机吗?。看下面这张图:

如果你感兴趣的话,可以去参考本文的附录,附录详细地给出了如何从申请编码入手,探索摇号系统的可能破绽。但能不能探索出来就不知道了。

那我们该怎么办?

一种方法是购买新能源汽车,中签率约为12分之一。开着新能源,六环可能都出不去就没电了(>_<)。

按照非官方说法,摇号政策可能在未来退出,并引入家庭单位摇号和征收拥堵费。但发出去的车牌不会回收,而一旦放开限购会导致疯狂购车,因为拥堵费太贵,大家塞满小区就是不出门:先把坑占上。这肯定也不是政府愿意看到的。至于之前传言的24次摇号没中者自动分配一个号码,我都不想告诉你24次以上没摇中的人有多少!传谣也要讲基本法啊。

通过以上分析,解决了沙漠君之前的疑惑,这套系统设计是符合规范的,抽签是随机和公平的。各位亲爱的读者,安心摇号,洗洗睡吧~/(ㄒoㄒ)。以后多绿色出行,为首都交通做出贡献。

备注和源代码

1.数据来源

来自bjhjyd.com,截至2016年6月摇号人数共计4394613人。但目前不确定学生是否能摇号。

对北京来说600万辆是一个红线,而北京作为全国示范,更愿意用行政而非经济手段来限制机动车数量,以表现公平。我国人口已经进入负增长,50年以后人口严重老龄化,我们老了之后开车可能会容易一些。

几年前可以网上查到每个中签人的名字,还有下面的新闻:

2. 假如系统真的有破绽呢?

(本段仅作为思想实验,开脑洞而已,请任何人不要对号入座。水表在门外,谢谢!)

通过控制种子,可以保证特定号码中签。但这样可能没法让所有要中签的都中签,策略是插入一些无效号。无效号能将特定的号码挤到对应必中的位置。

因为我们也无法判断参与抽签的每个号码都是有效的。而且你注意到了吗?2016年,每次摇号应该有15000个,但每次摇中的数量都差了一百多个,剩下的哪里去了?

通常计算机产生无效号,都是在短时间内集中产生的。如果能发现给每个用户分配编码的规则,就能反推用户的基本信息和注册时间,如果在统计上发现异常,就能找到这些无效号码,进而搜索随机种子。

沙漠君盯着这些长度都是13位的号码,统计了每一位上0-9字符出现的频率,发现它们都是等概率出现的。说明编码是按照某种随机算法生成的。什么工具的随机算法产生的字符长度是13位呢?我花了五六个小时破解这个逻辑:

我通过摇号程序签名,发现开发这套系统的公司叫taiji。我通过该公司网站的招聘信息和项目介绍,了解了验证软件是2014年1月6号下午开发开发,用了一个半月开发完,后台语言多半是C#。

据我猜测,每次会从后台随机产生不在数据库里的一个13位的随机数,作为新申请人的编码ID。理论上说,如果其系统用的是C#默认的随机生成器,那么就能通过暴力搜索的方法,找出每个编码生成的时间,也就是号码注册的时间,当然,这种计算的复杂度非常高,靠一己之力是很难完成的。

但我相信,以上这些推测都是瞎扯,这套系统一定是公平而完美的。

3.Hawk数据抓取工具

这是笔者耗时四年开发的数据抓取软件,目前已经开源,详情可参考沙漠之鹰的历史文章《如何从互联网抓取海量数据》。

4.生成真实摇号数据源代码

   /// <summary>/// 代表一个抽签序号/// </summary>public class Slot{public int Index { get; set; }public string ID { get; set; }}public class Period{public string Date { get; set; }public int Total { get; set; }public int Quota { get; set; }public string ID { get; set; }public string MD5 { get; set; }public int Seed { get; set; }}static void Main(string[] args){var root = @"北京摇号\";var table= File.ReadAllLines(root + "摇号列表.txt").Skip(1).Select(d=>d.Split('\t')).Select(d=>new Period(){ID=d[0],MD5=d[1],Seed=int.Parse(d[2])}).ToList();foreach (var period in table){Console.WriteLine(period.ID);List<Slot> slots=new List<Slot>();var folder = $"{root}摇号文件\\PersonCommonNumberPeriod{period.ID}";foreach (var file in Directory.GetFiles(folder)) {if (file.Contains("_"))slots.AddRange(File.ReadAllLines(file).Select(d => d.Split(',')).Select(d => new Slot {Index = int.Parse(d[0]), ID = d[1]}));else if(file.Contains("csv")){var datas= File.ReadAllLines(file);period.Date = datas[3];period.Total = int.Parse(datas[5]);period.Quota = int.Parse(datas[6]);}}   Random random=new Random(period.Seed);SortedDictionary<string,int> selecteddict=new SortedDictionary<string, int>(); while (selecteddict.Count<period.Quota){var selected = slots[random.Next(slots.Count)];if(selecteddict.ContainsKey(selected.ID))continue;selecteddict.Add(selected.ID,selected.Index);}File.WriteAllLines(folder+"\\"+"被选中号码.txt",selecteddict.Select(d=>d.Key+'\t'+d.Value));}Console.WriteLine("fuck the world");}

绝对公平?破解北京机动车摇号的秘密相关推荐

  1. 技术宅男揭秘:北京机动车摇号真的公平?

    [编者按]本文作者为蚂蚁金服人工智能部高级算法工程师墨眀(网名:沙漠之鹰),曾就职于三星研究院从事语音合成工作,擅长自然语言处理.网页爬虫和数据分析.本文为作者在加入蚂蚁金服之前的个人业余兴趣项目.本 ...

  2. 机器学习预测机动车摇号:神秘的第七位

    沙漠君按 上一篇帝都摇号文章在发布之后,总阅读量高达百万,不少读者觉得意犹未尽.当时成文过于仓促,很多细节没有理清. 两月磨一剑,看看我们能否解决下面的问题: 13位用户编码真的是随机的吗? 摇号池中 ...

  3. 愚人节汽车假新闻之北京取消摇号

    京籍首辆车无需摇号 "翻身把歌唱!" 北京小汽车摇号粉碎了多少人的买车梦.不过今天北京市摇号政策发生变化,在目前号码池摇号的基础上增加上牌资格筛查,北京户籍购买首台汽车无需摇号,二 ...

  4. 【数据安全案例】北京购车摇号查询系统出现信息泄露漏洞

    北京市小客车指标调控管理信息系统网站在公布摇号结果后,由于其网站设计的bug,在查询信息的时候会造成信息泄漏,例如这个报道有介绍.有中签者发现,登录系统后通过网页浏览的方式查看其中签通知书时,自己的申 ...

  5. 北京购车摇号满两年送车牌

    买车要参加购车摇号,因此一直对相关的新闻比较关注. 今天,看到了一则新闻,说的是购车摇号一到两年不被抽中,政府或考虑给予指标. 下面引用新闻的具体内容: 北京市首轮购车摇号今天上午10时在北京市交通委 ...

  6. 用计算机摇号算不算随机抽样,专家解读摇号原理:随机抽不等于随意抽(2)

    "操作上讲只要根据随机的方法产生种子,就没问题" 丁文兴:要保证抽样过程公平的难点,还在于产生随机数种子的时候,要保证随机性.因为计算机不像骰子,它是一个暗箱,大家会觉得其中可能有 ...

  7. 抽奖摇号系统随机性算法介绍

    参考视频教程:    **高并发高性能 Go语言开发企业级抽奖项目  ** 摘要 ===== 本文分析GO语言包中的"crypto/rand"和"math/rand&qu ...

  8. 苹果香港对付黄牛出新招:购买iPhone需摇号

    据中国之声<央广新闻>报道,继北京买车需摇号之后,香港零售店买iPhone要摇号了.苹果在香港官网开始进行登记并将以摇号的方式在零售店销售iPhone. 国内的消费者对苹果设备的追捧令苹果 ...

  9. 北京小客车摇号程序PHP版

    相信很多北京本地or北漂一族摇了N年车牌号的人大有人在,作为一个即将加入摇号大军的程序员,带着好奇心查看了一下摇号相关的规则和程序,是否公平公正公开公... 官方信息 温馨提示:摇号月的25日,在公证 ...

  10. 北京摇号系统服务器,支付宝“城市服务”平台可查询北京小客车摇号结果

    支付宝"城市服务"平台可查询北京小客车摇号结果 [TechWeb报道]9月7日消息,北京市交通委与支付宝达成合作,市内交通出行服务将登陆城市服务平台.市民在手机上进入支付宝&quo ...

最新文章

  1. 华为CodeCraft2017算法结果检查工具(包含测试用例展示)
  2. 获奖公布 | Hello,SDK!数据采集黑客松大赛完美落幕!(含活动预告)
  3. 对于SpringMVC框架使用的时候出现“警告: No mapping found for HTTP request with URI [/login]”的问题解决方案...
  4. HTML5 API详解(6):getUserMedia实现拍照功能
  5. 使用p2p发送GB28181流的设计
  6. Confluence 6 配置 workbox 通知
  7. 64位浮点数_C语言常见面试题解析(1)——浮点数的比较
  8. Win32汇编---控件的超类化感想
  9. 1077. 互评成绩计算 (20)-PAT乙级真题
  10. LeetCode 221. 最大正方形(动态规划)
  11. 编译华硕路由器ACRH17源代码小记
  12. WPF随笔(十)--使用AvalonDock实现可停靠式布局
  13. java snakeyaml_java – 使用SnakeYAML的嵌套构造
  14. mysql主从配置修改重启无效
  15. 手机号码邮箱 验证规则(最新)
  16. 如何统计自己写的代码量
  17. 该网页无法正常运作 目前无法处理此请求。 HTTP ERROR 500
  18. 全网最简单的RFM模型制作方法,3岁小孩都能学会!
  19. 医院信息管理系统论文java_毕业论文-基于java的医院门诊信息管理系统设计与实现...
  20. 亳州工业学校计算机,2018亳州市中专讲师助讲专业技术职务评审结果公示

热门文章

  1. java取0到999整数_Java中输入一个0到999的整数 怎么弄? 谢谢了、
  2. 龙芯电脑编译安装mysql5.7详解
  3. treeset可以重复吗_社保和商业医疗险可以重复报销吗?报销攻略请收好
  4. 【点宽专栏】研报复现——跨期价差分析与跨期套利研究
  5. Nginx之13运筹帷幄 - (VeryNginx)
  6. python面板数据分析代码_面板数据分析是什么如何进行面板数据分析?
  7. 数据结构——学期总结
  8. excel一列求和_EXCEL表格怎么自动求和?4种典型批量求和套路
  9. Infectious Media Generator失败
  10. 怎样批量将图片转成PDF格式?图片转换PDF操作方法