随机动物生成器

从 24 种动物与 16 个栖息地的词库里按种子抽取组合,共 384 种搭配;每条给出动物名、分类、栖息地与体重,撞名自动重试并把重试次数标出来。种子不变,同一批结果逐字复现。

默认示例:种子 20261101、条数 12、全部分类。词库 24 种动物 × 16 个栖息地 = 384 组合,撞名时最多再抽 8 次。
种子 20261101 | 数量 12 | 分类 全部(24 种 × 16 栖息地 = 384 组合) -- 12 条生成结果 -- 1 蓝鲸 哺乳 沙漠 150000 kg 2 树懒 哺乳 雨林 6 kg (撞名重试 1 次) 3 非洲象 哺乳 洞穴 6000 kg 4 变色龙 爬行 森林 500.0 g 5 螳螂虾 节肢 山地 100.0 g (撞名重试 2 次) 6 企鹅 鸟 苔原 30 kg 7 猫头鹰 鸟 海洋 2 kg 8 绿海龟 爬行 沙漠 160 kg (撞名重试 1 次) 9 猎豹 哺乳 苔原 50 kg 10 金雕 鸟 珊瑚礁 6 kg 11 科莫多巨蜥 爬行 海洋 90 kg 12 箭毒蛙 两栖 雨林 2.0 g 合计撞名重试 4 次 -- 批量种子(各取前 6 条)-- seed 20261101 : 蓝鲸、树懒、非洲象、变色龙、螳螂虾、企鹅 seed 1 : 科莫多巨蜥、企鹅、章鱼、大白鲨、变色龙、猎豹 seed 42 : 箭毒蛙、变色龙、绿海龟、狼蛛、三文鱼、科莫多巨蜥 seed 2026 : 猎豹、蓝鲸、大白鲨、北极狐、金雕、大鲵

默认示例:种子 20261101 生成 12 条。条数、种子、分类任意一项改动即重新生成,光标停在条数或种子框里按回车同样触发一次;批量种子框按 Ctrl+Enter(Mac 上 Cmd+Enter)重算。

使用方法

  1. 「生成条数」默认 12,允许 1 到 24;「随机种子」默认 20261101,允许 0 到 2147483647。改任意一项立刻重算,光标停在条数或种子框里按回车同样触发一次生成。
  2. 「分类筛选」默认全部,也可以锁定哺乳、鸟、爬行、两栖、鱼、节肢、软体中的某一类。筛选后只在该类里抽取,可选条数随之变小,撞名会更早出现。
  3. 结果区先给一行「种子 / 数量 / 分类」概要,再逐条列出动物名、分类、栖息地与体重,末尾给出撞名重试合计次数。
  4. 「批量种子」框默认写了四个种子,每行一个整数,各取前 6 条横向对比;按 Ctrl+Enter(Mac 上 Cmd+Enter)重算,被清空时点生成会自动填回。
  5. 概要下面是明细表,默认显示 6 行,点「加载更多」展开全部,点「导出 CSV」存成带字节序标记的文件,Excel 打开不乱码。
  6. 「复制结果」复制整段清单;「复制对照表」复制正文那张撞名概率表的 TSV,可直接粘进表格。
  7. 想复现某一批结果,记下种子、条数、分类三项即可:同样的三项输入,任何时候打开都得到逐字相同的一批。
  8. 条数不是整数、超出 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%。

抽取条数全不重复概率撞名概率
1100.0000%0.0000%
295.8333%4.1667%
387.8472%12.1528%
476.8663%23.1337%
564.0553%35.9447%
650.7104%49.2896%
826.9399%73.0601%
1011.2250%88.7750%
123.5468%96.4532%
150.3387%99.6613%
200.0006%99.9994%
240.0000%100.0000%

下面这张是词库里最轻到最重的八个体重档,最重与最轻相差 300000000 倍。读的时候配合上面那批示例一起看,就能明白为什么体重必须单列一列。

动物分类体重
帝王蝶节肢0.5 g
箭毒蛙两栖2.0 g
蜂鸟鸟5.0 g
金雕鸟6 kg
大白鲨鱼1100 kg
非洲象哺乳6000 kg
蓝鲸哺乳150000 kg
最重 / 最轻—300000000 倍

结果边界、舍入与适用说明

常见问题

同一个种子为什么每次生成的结果都一样?换一批要怎么换?

因为用的是确定性伪随机数发生器,状态按(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。

这个工具免费吗?

免费,无需注册即可使用。

输入的数据安全吗?

安全。计算在当前浏览器本地完成,不会上传输入内容。

相关工具