使用方法
- 在「生成数量」填 10(示例值),允许 1~100 的整数。
- 「性别口径」默认「不限」。选「男」或「女」时,名用字只从对应的 30 字库里取;选「不限」时从两个库合并后的 60 字池里取。
- 「名长度」默认「随机」,按 80% 双字名、20% 单字名的比例输出;也可以固定成全部单字名或全部双字名。
- 「姓氏范围」默认「只用单姓」。「允许复姓」开启后,约有 8% 的条目会落到欧阳、司马、上官这类复姓上,用来测长姓氏的排版。
- 点「立即生成」,结果区每行一个姓名。点「复制全部」带走纯姓名列表,点「导出结果 CSV」带走带序号、姓氏、名、性别四列的文件。
这个虚拟姓名生成器能解决什么问题
一是造测试数据。做后台、报表或接口联调时,姓名列经常被随手填成「张三、李四、张三、李四」,几行之后就分不出哪条是哪条。这里一次给 100 个互不重复的中文姓名,直接粘进 SQL 或 CSV 就能用。
二是给记录做匿名化。把真实姓名替换成虚构姓名再拿去演示、截图、给外包看,比打码更干净:字段长度、字面色调都和真实数据接近,界面不会被撑破,也不必担心哪一列漏遮。
三是压排版边界。中文姓名的长度从 2 字(单姓 + 单字名)到 4 字(复姓 + 双字名)都有。开启「允许复姓」并把名长度固定成双字名,就能专门产出 4 字姓名,用来验证表格列宽、头像截断、卡片换行这些容易出问题的地方。
四是按真实分布造数据。很多生成器把姓氏平均分配,于是「王」和「高」出现次数一样多,看着就不像真的。本页的虚拟姓名生成器是按人口占比加权抽姓氏的,前 20 个大姓合计覆盖率约 54%,其中「王」约占 7.25%,做出来的分布更接近真实户籍样本。
本页只覆盖中文人名这一类场景。它不是实名认证工具,也不做身份核验:输出的姓名是随机组合的虚构结果,与任何真实个人无关,请不要拿它去注册账号或办理任何需要实名的业务。
生成原理:姓氏加权抽样与名字用字组合
姓氏的抽取是整个工具里唯一需要「不均匀」的一步。做法是先把 20 个姓氏的权重按顺序累加成一条递增序列 [7.25, 14.44, 21.27, … 54.13],再取一个 Math.random() × 54.13 的随机数,用二分查找找到第一个不小于它的累积值,返回那个位置上的姓氏。二分查找的循环是 while (lo < hi) { mid = (lo + hi) >> 1; … },20 个候选最多比较 5 次,比从头遍历一遍短。
为什么不用「按权重把姓氏重复铺进一个大数组再均匀抽」?那样也能得到同样的分布,但要先展开成上万个元素的表,既占内存又难维护;把权重留在表里、用累积权重 + 二分查找,20 个数字就够,改一个权重也只动一个位置。
名用字的抽取走的是另一条路:先按性别选池——男名 30 字、女名 30 字、两者没有重叠,合并后是 60 字——再从池里抽。这里用的是 Math.floor(Math.random() × n),也就是乘法取整而不是取模。很多人写随机取下标时习惯写 Math.floor(Math.random() * n) % n,末尾那个 % n 毫无作用还容易被误读;真正的取模偏置出现在另一种写法里:先生成一个整数再用 % 截断到 n,因为整数上界通常不是 n 的整数倍,前缀几个下标会多出现一次。本页不生成整数,所以没有这个问题。
双字名是不放回抽两字:第一字从池里取一个,第二字重抽直到与第一字不同。对男名或女名池(各 30 字)来说,双字名的组合数是 30 × 29 = 870 种,加上 30 种单字名,限定一个性别、一个姓氏时共有 900 种写法;「不限」性别时池变 60 字,双字名 60 × 59 = 3540 种,合计 3600 种。这个量级决定了批量生成的上限:一次 100 条,20 个单姓下理论空间是 20 × 3600 = 72000 种,够用。
姓氏加权抽样负责「像真的」,用字均匀抽样负责「够散」,最后一层是批内去重:生成时用一个集合记住已经出现过的完整姓名,重复的丢弃重抽,最多重试 60 倍于目标条数,撑满就报错而不是悄悄塞重复值。
还有一处刻意的取舍:这里故意用 Math.random() 而不是加密随机数。虚构姓名不是凭据,不需要防预测;加密接口每次调用都要过一遍操作系统熵池,批量生成 100 条时明显更慢。反过来说,如果你要把生成结果当占位口令或 token 使用,那就不该用本页,请改用取自 crypto.getRandomValues 的密码类工具。
完整示例(数值仅作演示)
示例条件与页面打开时的默认值完全一致:数量 10、性别不限、名长度随机(双字名 80%)、只用单姓。此时名用字池是 60 字,单姓下组合空间 3600 种。
- 姓氏加权后,10 条里出现「王」的期望条数约为
10 × 7.25% = 0.73条;出现「高」的期望只有10 × 0.84% = 0.08条,差 8.6 倍。 - 10 条里不出现任何重复姓名的概率,在不做去重、纯随机的模拟中是 99.69%(10 万次蒙特卡洛);工具本身做了去重,所以这一项恒为 100%。
- 若把数量提到 100 且关掉去重,出现重复的概率会升到约 28.86%——这也是为什么去重必须做。
- 10 条里预计有 8 条是双字名、2 条是单字名(80% / 20%)。
下面这一组是默认条件下真机生成的结果,仅作排版演示,你点一次「立即生成」得到的会是另一批:
王浩宇 / 李欣怡 / 张泽轩 / 陈静涵 / 刘晨阳 / 杨雪薇 / 黄明轩 / 赵瑞琪 / 吴宇航 / 周明辉
姓氏分布与名字用字组合对照表
下表是虚拟姓名生成器内置的姓氏权重表,按公开报道的《全国姓名报告》口径整理,用于加权抽样,不是人口普查精确值;「约人口」按 14 亿人口口径换算,仅用于说明量级。
| 姓氏 | 加权占比 | 累计占比 | 约人口(14 亿口径) |
|---|---|---|---|
| 王 | 7.25% | 7.25% | 约 10150 万 |
| 李 | 7.19% | 14.44% | 约 10066 万 |
| 张 | 6.83% | 21.27% | 约 9562 万 |
| 刘 | 5.38% | 26.65% | 约 7532 万 |
| 陈 | 4.53% | 31.18% | 约 6342 万 |
| 杨 | 3.08% | 34.26% | 约 4312 万 |
| 黄 | 2.29% | 36.55% | 约 3206 万 |
| 赵 | 2.23% | 38.78% | 约 3122 万 |
| 吴 | 2.05% | 40.83% | 约 2870 万 |
| 周 | 1.93% | 42.76% | 约 2702 万 |
| 徐 | 1.45% | 44.21% | 约 2030 万 |
| 孙 | 1.38% | 45.59% | 约 1932 万 |
名字用字则按下面的池子取字,两个池子没有交集,所以「不限」性别时的 60 字等于两池之和,不会因为去重缩水:
| 池子 | 字数 | 示例用字 |
|---|---|---|
| 男名用字 | 30 | 伟 强 磊 军 洋 勇 杰 涛 明 超 刚 平 辉 健 鹏 宇 浩 晨 睿 泽 轩 昊 阳 帆 铭 博 瑞 航 峰 毅 |
| 女名用字 | 30 | 芳 娜 静 敏 丽 娟 艳 燕 霞 婷 悦 欣 怡 晗 瑶 萱 琳 妍 蕊 琪 月 雪 梅 兰 莉 蕾 颖 涵 晴 薇 |
| 不限(合并) | 60 | 以上两组直接拼接,重叠字数为 0 |
把池子和姓氏合起来看,就能算出各档的组合空间:
| 性别口径 | 名用字池 | 单字名 | 双字名(不放回) | 单姓下合计 |
|---|---|---|---|---|
| 男 | 30 | 30 | 870 | 900 |
| 女 | 30 | 30 | 870 | 900 |
| 不限 | 60 | 60 | 3540 | 3600 |
| 不限 + 复姓 | 60 | 60 | 3540 | 3600(复姓另有 8 × 3600) |
另外,复姓开启后并不是按人口占比抽的——真实复姓人口占比不足 0.1%,照原样抽几乎一辈子见不到一个,所以这里刻意放大到 8%,纯粹为了让你能测到 4 字姓名,这属于演示性放大,不代表真实分布。
输入范围、边界与精度说明
下面这些不是「限制」,而是刻意设定的边界;知道它们,才不会把这个虚拟姓名生成器当成万能工具用。
- 生成数量 1~100 的整数。0、负数、小数、字母和空值都会被拒绝并给出提示。上限设 100 是因为结果区是一段文本,再多会让页面渲染明显变慢。
- 「性别口径」只影响用字池,不影响正确性。选「男」时输出里不会出现女名用字,反之亦然;选「不限」时两池混合,因此单条结果的性别倾向可能不明显。
- 双字名两字必然不同。第二字会重抽直到与第一字不同,所以不会出现「王刚刚」这种叠字;如果你确实需要叠字(比如测「李蕾蕾」这类真实存在的名字),本页给不了。
- 批内去重是有上限的。去重靠「丢弃重抽」,最多重试目标条数的 60 倍。当前空间(20 个单姓 × 3600 = 72000 种)远超 100 条,所以正常不会触发;一旦触发,页面会明确报错,而不是输出重复值。
- 「互不重复」只保证同一批次内部。分两次各生成 10 条再合并,两批之间完全可能撞名——这和生日问题一样,样本越分散、池子越小越容易撞。
- 输出的姓名全部是虚构组合。它与真实户籍数据没有对应关系,也不做重名率校验;如果你需要的是真实分布下的重名概率,那是另一回事。
- 本页不联网。姓氏表、用字池和随机逻辑都在页面脚本里,没有任何请求发出;想验证就打开开发者工具的 Network 面板点几次生成。
常见问题
生成的姓名会不会和真人对上?
会撞上真实存在的姓名组合,这不奇怪——中文姓名本身就是「姓氏 + 常用字」的组合,「王浩宇」这种写法在现实中一定有人叫。区别在于:本页的姓名是随机拼出来的,不指向任何具体个人,也没有关联身份证号、地址、手机号等信息。它只是长相逼真的占位字符串。
为什么「王」出现得比「高」多这么多?
因为姓氏是按人口占比加权的。内置表里「王」占 7.25%、「高」占 0.84%,相差约 8.6 倍,所以随机抽 10 条时「王」的期望条数是 0.73、「高」只有 0.08。如果两个姓氏出现次数一样多,说明那个工具是平均分配姓氏的,做出来的数据反而不像真实样本。
这 20 个姓氏的占比是从哪来的?
按公开报道的公安部《全国姓名报告》常见姓氏排序与占比口径整理,本页只把它当作加权权重使用。它不是人口普查的精确值,也不随年份更新;如果你要的是严谨的统计分析,应当回到原始报告取数,而不是用本页的表。
为什么复姓被放大到 8%?
真实复姓人口占比不足 0.1%,照原样抽取的话,生成 100 条也几乎抽不到一个,测不到「复姓 + 双字名」这种 4 字最长情形。开启后按 8% 抽查,是刻意放大以便触发边界,页面也把这件事标明了——别把它当成真实分布。
为什么不用加密随机数生成?
因为虚构姓名不是凭据,不需要防预测,而 crypto.getRandomValues 每次都要过操作系统熵池,批量生成时更慢。这里的取舍是「够用即止」。反过来,如果生成结果要当占位口令、验证码或 token,请改用基于 crypto.getRandomValues 的密码类工具,别用本页。
双字名为什么不用「放回」抽样?
放回会产出叠字名(如「刚刚」「蕾蕾」)。虽然真实姓名里确实有叠字,但作为占位数据,叠字容易和「复制粘贴出错」混淆。改用不放回后,男名或女名双字名的组合数从 900 降到 870,代价很小,换来的是结果更干净可读。
一次生成的 100 条会重复吗?
不会。工具在批内做了去重,重复的完整姓名会被丢弃重抽,所以输出恒为互不重复。要注意的是「跨批次」不保证:两次各生成 100 条再合并,撞名是正常的。若要合并,请把两批结果一起重新生成,或者自行按姓名列去重。
「导出结果 CSV」和「复制姓氏对照表」有什么区别?
前者导出的是生成结果:序号、姓名、姓氏、名、性别四列,带 UTF-8 BOM,Excel 直接打开不乱码。后者是把姓氏分布表按 TSV 复制到剪贴板:姓氏、加权占比、累计占比、约人口,粘进表格软件会自动按列分开。