使用方法
- 「生成条数」默认 12,允许 1 到 24;「随机种子」默认 20261101,允许 0 到 2147483647。改任意一项立刻重算,光标停在条数或种子框里按回车同样触发一次生成。
- 「分类筛选」默认全部,也可以锁定哺乳、鸟、爬行、两栖、鱼、节肢、软体中的某一类。筛选后只在该类里抽取,可选条数随之变小,撞名会更早出现。
- 结果区先给一行「种子 / 数量 / 分类」概要,再逐条列出动物名、分类、栖息地与体重,末尾给出撞名重试合计次数。
- 「批量种子」框默认写了四个种子,每行一个整数,各取前 6 条横向对比;按 Ctrl+Enter(Mac 上 Cmd+Enter)重算,被清空时点生成会自动填回。
- 概要下面是明细表,默认显示 6 行,点「加载更多」展开全部,点「导出 CSV」存成带字节序标记的文件,Excel 打开不乱码。
- 「复制结果」复制整段清单;「复制对照表」复制正文那张撞名概率表的 TSV,可直接粘进表格。
- 想复现某一批结果,记下种子、条数、分类三项即可:同样的三项输入,任何时候打开都得到逐字相同的一批。
- 条数不是整数、超出 1 到 24、种子不是整数,或批量种子某一行写成英文或小数,都会给出针对该条的具体提示,不拿上一次的结果冒充本次输出。
这个随机动物生成器能解决什么问题
第一类是冷启动时「想不到该用谁」。写故事需要角色、做课件需要例子、给测试账号起名需要一批互不相同的词,不如先让程序吐出十几条候选:默认种子下第一条就是蓝鲸,体重 150000 kg,旁边跟着分类与栖息地,挑起来有依据。
第二类是「同一批里自己撞了自己」。从 24 种动物里不放回地抽 12 条,撞名概率是 96.4532%,也就是几乎必然会抽到重复项。本页在抽到已出现的动物时最多再抽 8 次,并把每条的重试次数照实标出来,不会悄悄去重而让序列错位。
第三类是跨时间、跨人对不上。口头说「我用那个动物生成器跑了一批」没有意义,因为换台机器结果就变了。本页用确定性伪随机数,种子相同则逐字复现,把种子记进文档就能让同事看到完全一致的一批。
第四类是筛选场景下的容量错觉。锁定「软体」只有 2 种可选,却要生成 12 条,这时撞名不是概率问题而是必然——不放回抽样一旦超过词库容量,重复一定发生,重试机制只能把重复推迟到 8 次之后。
这个工具在本站也叫「随机动物生成器」,词库里的 24 种动物与 16 个栖息地各自独立抽取,下面会讲清为什么会出现「蓝鲸 + 沙漠」这种现实中不存在、程序上却有效的组合。
计算原理与变量说明
词库是两个互相独立的池:动物池 24 条,每条带分类与体重;栖息地池 16 个。两个池相乘得到 384 种组合。分类分布是哺乳 6 种、鸟 4 种、爬行 3 种、两栖 2 种、鱼 3 种、节肢 4 种、软体 2 种,合计 24。
每生成一条,先抽动物再抽栖息地,两次抽取各消耗一个随机数。栖息地不与动物做任何生物学匹配,所以会出现「蓝鲸 + 沙漠」「企鹅 + 珊瑚礁」这类错位组合——这是设计上的取舍:保持两个池独立,才能让组合数稳定在 384,也让同一颗种子在不同版本之间仍能复现。
随机数用 32 位线性同余发生器:状态 s 每次更新为(s × 1103515245 + 12345)对 2^31 取模,写成 s = (Math.imul(s, 1103515245) + 12345) & 0x7fffffff。乘法必须用 Math.imul 而不是普通的 *:s 与 1103515245 相乘的结果会超过 2^53,普通乘法按双精度浮点求值会丢掉低位,序列就不再是同一条,换台浏览器结果就对不上;Math.imul 做的是 32 位整数乘,结果与 C 语言的实现一致。
取词下标是 Math.floor(rnd() / 2147483647 * arr.length),把 0 到 2^31−1 的整数线性映射到池长度上。分母写成 2147483647 而不是 2147483648,是让下标永远落在 0 到 length − 1 之内,即使随机数取到上界也不会越界。
LCG 的周期与低位问题。取模 2^31 的线性同余发生器周期最多 2^31,低位比特的随机性明显比高位差,往往按很短的周期循环。本页先除以 2^31−1 再乘池长度来缓解;真要做密码学用途的随机数,应该用 crypto.getRandomValues 而不是 LCG。
撞名概率是怎么来的。从 24 项里不放回抽 n 项,全不重复的概率是 Π(24 − i) / 24(i 从 0 到 n − 1),撞名概率就是 1 减这个值。它随 n 超线性上升:抽 5 条是 35.9447%,抽 10 条是 88.7750%,抽 15 条是 99.6613%,抽 20 条是 99.9994%;抽到 24 条时等于词库容量,撞名概率 100%。
变量一共三个:条数、种子、分类。种子决定整条序列的起点,条数决定消耗多少个随机数,分类决定动物池的长度;三者确定,输出唯一确定。
完整示例(数值仅作演示)
默认示例是种子 20261101、条数 12、全部分类,前 12 条逐字如下:蓝鲸(哺乳 / 沙漠 / 150000 kg)、树懒(哺乳 / 雨林 / 6 kg,撞名重试 1 次)、非洲象(哺乳 / 洞穴 / 6000 kg)、变色龙(爬行 / 森林 / 500.0 g)、螳螂虾(节肢 / 山地 / 100.0 g,撞名重试 2 次)、企鹅(鸟 / 苔原 / 30 kg)、猫头鹰(鸟 / 海洋 / 2 kg)、绿海龟(爬行 / 沙漠 / 160 kg,撞名重试 1 次)、猎豹(哺乳 / 苔原 / 50 kg)、金雕(鸟 / 珊瑚礁 / 6 kg)、科莫多巨蜥(爬行 / 海洋 / 90 kg)、箭毒蛙(两栖 / 雨林 / 2.0 g)。合计撞名重试 4 次。
这 4 次重试全部集中在第 2、5、8 条上:第 2 条第一次抽到的蓝鲸已出现过,重抽得到树懒;第 5 条连撞两次才落到螳螂虾;第 8 条重抽一次得到绿海龟。其余 9 条一次抽中。
换种子看差异。种子 1 的前 6 条是科莫多巨蜥、企鹅、章鱼、大白鲨、变色龙、猎豹;种子 42 是箭毒蛙、变色龙、绿海龟、狼蛛、三文鱼、科莫多巨蜥;种子 2026 是猎豹、蓝鲸、大白鲨、北极狐、金雕、大鲵。三批之间没有共同前缀,说明序列起点对输出的影响是全局的,不是只改第一条。
体重跨度在同一批里也看得出来:最重的蓝鲸 150000 kg 与最轻的箭毒蛙 2.0 g 相差 7 个数量级。体重单列一列,是为了避免把鲸和蛙放进同一个对比场景。
组合空间与撞名概率对照表
下表是不放回抽取下的撞名概率,词库容量 24。抽的个数越多,撞名概率涨得越快,超过 24 之后概率恒为 100%。
| 抽取条数 | 全不重复概率 | 撞名概率 |
|---|---|---|
| 1 | 100.0000% | 0.0000% |
| 2 | 95.8333% | 4.1667% |
| 3 | 87.8472% | 12.1528% |
| 4 | 76.8663% | 23.1337% |
| 5 | 64.0553% | 35.9447% |
| 6 | 50.7104% | 49.2896% |
| 8 | 26.9399% | 73.0601% |
| 10 | 11.2250% | 88.7750% |
| 12 | 3.5468% | 96.4532% |
| 15 | 0.3387% | 99.6613% |
| 20 | 0.0006% | 99.9994% |
| 24 | 0.0000% | 100.0000% |
下面这张是词库里最轻到最重的八个体重档,最重与最轻相差 300000000 倍。读的时候配合上面那批示例一起看,就能明白为什么体重必须单列一列。
| 动物 | 分类 | 体重 |
|---|---|---|
| 帝王蝶 | 节肢 | 0.5 g |
| 箭毒蛙 | 两栖 | 2.0 g |
| 蜂鸟 | 鸟 | 5.0 g |
| 金雕 | 鸟 | 6 kg |
| 大白鲨 | 鱼 | 1100 kg |
| 非洲象 | 哺乳 | 6000 kg |
| 蓝鲸 | 哺乳 | 150000 kg |
| 最重 / 最轻 | — | 300000000 倍 |
结果边界、舍入与适用说明
- 条数为空时提示请填 1 到 24 之间的整数,不拿上一次的结果冒充本次输出。
- 条数写成 12.5 这类小数时提示必须是整数;写成 0 或 25 时提示超出 1 到 24 的范围。
- 种子为空或不是整数时提示请填 0 到 2147483647 之间的整数,只有同种子才能复现同一批结果。
- 批量种子某一行出现小数、负数或非数字时,报出具体行号与内容,例如「批量种子第 3 行「abc」不是整数」。
- 撞名重试最多 8 次:8 次都抽到重复项时保留最后一次结果,本批可能出现重名,重试次数照实显示。
- 筛选后的可选条数少于所需条数时,结果里必然出现重名;这不是缺陷,是不放回抽样超过词库容量的必然结果。
- 体重小于 1000 g 按克显示并保留一位小数,大于等于 1000 g 按千克显示;能整除时不带小数。
- 页面不联网、不写本地存储,种子与条数只用于本次计算。
常见问题
同一个种子为什么每次生成的结果都一样?换一批要怎么换?
因为用的是确定性伪随机数发生器,状态按(s × 1103515245 + 12345)对 2^31 取模推进,起点由种子决定,同一种子必然走出同一条序列。想换一批就改种子:种子 1 给出科莫多巨蜥、企鹅、章鱼、大白鲨、变色龙、猎豹,与种子 20261101 完全不同。
为什么会出现「蓝鲸 + 沙漠」这种现实中不可能的组合?
因为动物池与栖息地池是两个互相独立的池,各抽各的,不做生物学匹配。这样设计是为了让组合数稳定在 24 × 16 = 384,并保证同一颗种子在任何版本里都能复现。若需要现实可行的搭配,把筛选与人工复核结合起来用,本页不提供生态约束。
撞名重试 8 次都没抽到新的动物怎么办?
重试上限是 8 次,用尽后保留最后一次抽到的动物,本批可能出现重名。结果区会把每条的重试次数照实显示,不会隐藏;看到重试次数普遍不为 0,说明当前条数与分类的组合已经逼近词库上限,应减少条数或放开筛选。
抽 12 条为什么会撞名?24 种动物不是够用吗?
不够。从 24 项里不放回抽 12 条,全不重复的概率只有 3.5468%,撞名概率 96.4532%。撞名概率随条数超线性上升,因为每新增一条都要和前面所有条逐一比对;抽 5 条时还只有 35.9447%,抽 10 条就到 88.7750% 了。
为什么必须用 Math.imul,直接写 s * 1103515245 不行吗?
不行。s 最大接近 2^31,乘 1103515245 的结果接近 2^61,远超双精度浮点能精确表示的 2^53,普通乘法会丢掉低位并让不同浏览器给出不同序列。Math.imul 做 32 位整数乘,结果与 C 语言实现一致,序列才能跨环境一致。
LCG 生成的随机数能当密码或令牌用吗?
不能。线性同余发生器状态只有 32 位,低位比特周期很短,拿到连续几个输出就能反推后续序列。它只适合做抽样、演示与可复现的名单;涉及密钥与令牌的场景必须用 crypto.getRandomValues。
这个工具免费吗?
免费,无需注册即可使用。
输入的数据安全吗?
安全。计算在当前浏览器本地完成,不会上传输入内容。