去年年会前,HR 递来一张手写奖项清单:一等奖 iPhone、二等奖 耳机、三等奖 保温杯、鼓励奖 纸巾一提,最下面单独一格「谢谢参与」。她的要求只有一句,谢谢参与要占一半,又别让台下看穿那格是空的。我在 Excel 里凑了三轮百分比,分母始终对不上;后来换了思路,不凑比例,只给每项写权重。这篇记的就是这条链,以及两种抽法下第几个被抽到的人吃不吃亏。
一、权重合计 60:占比、扇区角度、300000 次实测
清单我填进 幸运转盘抽签 的抽奖权重预设,五项权重是 1、3、6、20、30,合计 60;占比是每项除以 60,扇区角度按同一个比值铺开。我又用固定种子(mulberry32,20261021)跑了 300000 次加权抽取核对,同种子重跑数值不变。
| 奖项 | 权重 | 理论占比 | 扇区角度 | 实测频率 | 相对偏差 |
|---|---|---|---|---|---|
| 一等奖 iPhone | 1 | 1.6667% | 6.0° | 1.70% | 1.70% |
| 二等奖 耳机 | 3 | 5.0000% | 18.0° | 4.95% | -0.93% |
| 三等奖 保温杯 | 6 | 10.0000% | 36.0° | 9.96% | -0.39% |
| 鼓励奖 纸巾一提 | 20 | 33.3333% | 120.0° | 33.37% | 0.11% |
| 谢谢参与 | 30 | 50.0000% | 180.0° | 50.02% | 0.04% |
第一行那两个 1.70% 要分开读:实测频率 1.70% 是 300000 次里一等奖命中的比例,理论值 1.67%(精确 1.6667%);最后一列是(实测 - 理论)除以理论,恰好也写成 1.70%,讲的是比理论高了约百分之一点七,不是机会本身。二等奖就拉开了,4.95% 对 5.00%、偏差 -0.93%,这类差是抽样噪声,样本再大也只逼近理论。
二、放回:每轮独立,撞名是迟早的事
不勾「抽中移除」时每轮都是原样 40 项、单项概率 2.5000%,上一轮不影响下一轮,会出问题的是转几次就撞回同一个人。下表只算放回,不放回的数在第三节,两套数不并排看。
| 转动次数 | 全部不重复 | 至少一次重复 |
|---|---|---|
| 2 | 97.5000% | 2.5000% |
| 3 | 92.6250% | 7.3750% |
| 5 | 77.1103% | 22.8897% |
| 8 | 47.3144% | 52.6856% |
| 10 | 29.3349% | 70.6651% |
| 15 | 4.8989% | 95.1011% |
| 20 | 0.3050% | 99.6950% |
抽满 20 次至少撞一次是 99.6950%,抽到 30 次全不重复只剩 1.950e-7,当作必然重复;反过来要把 40 项全露过一面,期望约 171.14 次(coupon collector),比直觉慢得多。
三、不放回:分母每轮少一项,顺序不偏
班会抽 3 个人值日,有人当场问第二个被抽到的是不是吃亏。6 项等权摊开:单项概率从 16.67% 起,抽中即移除,第 2 轮 20.00%、第 3 轮 25.00%、第 4 轮 33.33%,最后只剩「乙、己」。分母每轮少 1,概率一路抬上来,可那是每轮的条件概率,不是某人最终被选中的概率。
该算的是后者:40 人不放回抽 3 人,某人在这 3 人中的概率 = 3/40 = 7.50%。第 k 位是某个指定的人,k=1、2、3 都是 1/40 = 2.5000%,第 2 位是 39/40 乘 1/39,仍是 2.5000%,后抽不吃亏。有序无序怎么分见 排列与组合的区别。勾了移除也要 opts.length > 2 才真删,只剩 2 项时只提示不停删。
四、输入格式:哪些写法认、哪些会被改掉
一行一项,名称与权重之间半角冒号、半角逗号、全角冒号、全角逗号都认,张三:3、李四,2、王五:1 进的是同一个转盘,#注释行 与空行直接忽略。年会那份我这样敲:
一等奖 iPhone:1
二等奖 耳机:3
三等奖 保温杯:6
鼓励奖 纸巾一提:20
谢谢参与:30
- 权重只认正数:
香蕉:0、橘子:-5、桃:abc都按 1 处理,非正数不会让某项中不了,只占一格权重 1 的扇区。 - 名称含冒号时按最后一个分隔符切,
苹果::2是名称「苹果:」加权重 2、F:1.5:2是名称 F:1.5 加权重 2;同一行混用分隔符也不拆两项,火锅:2, 麻辣烫:3是一整项、权重 3。 - 显示最多两位小数,
0.333显示 0.33、2.675显示 2.68,计算仍用原值,6 项 A:1.5 / B:1.5 / C:0.333 / D:2.675 / E:1e3 / F:1.5:2 合计 9.01;这不等于只能填两位。 - 科学计数法不认,行解析只匹配 \d+(\.\d+)?,
E:1e3整行当名称、权重 1,不会变成 1000;权重 1 的项回写时省略冒号,X:1存成X。
五、指针不压线,结果与画面同源
落点是 jitter = span × (0.14 + rand × 0.72),指针只在扇区内部 14% 到 86% 处停,60 项等权每项 6° 时最小间距 0.84°。转盘固定多转 5、6 或 7 圈再加对齐角,时长 3.6 到 5 秒随机;停止结果由最终角度反查指针所在扇区,绘制与判定共用一套角度。选人靠 Math.random() 乘权重合计逐项减掉的累减法,减到不大于 0 的那项胜出,概率等于权重占比,但那是伪随机不是物理随机,承诺不了绝对公平。
名单定稿后走分享链接,选项与权重编码进网址的 #opts= 片段,对方打开就是同一个转盘。它只是 URL 片段,不进服务器,也没有多端同步,回读不足 2 项会被拒。15 字符(含 3 个换行)编成 48 字符,中文 3 行 UTF-8 22 字节编成 32 字符、URL 里 36 字符。只给 40 人名单排序、不必逐项开奖,文件随机抽取 更省事。
Q:权重能填小数吗?
能,只按相对比例生效,填 1 和 2 与填 1.5 和 3 是同一个转盘;显示只留两位,参与换算的是原值。
Q:抽中移除和不移除,概率怎么变?
不移除时 40 项每轮单项概率都是 2.5000%,抽 3 次至少一次重复 7.3750%;移除时分母每轮少 1、单项概率逐轮抬高,40 人抽 3 人某人入组 7.50%。
Q:能不能把名单发给同事?
能,名单进 URL 的 #opts= 片段,对方打开即还原同一个转盘;服务器那边没存东西,也不存在两个人改同一份。
回到 HR 那一格,她拿走的是权重 1、3、6、20、30 这张表,谢谢参与 50.0000%、扇区 180.0°。年会不勾移除,奖池不该越转越小,代价是抽满 10 次有 70.6651% 的概率撞回同一个名字;班会勾移除,要的是 3 个不同的人,代价是单项概率涨到 33.33%。两种抽法没有谁更公平,只有谁配得上玩法。