如何将特定范围整数唯一随机映射至同范围并生成AAA-nnn格式编码
序列号转AAA-nnn格式唯一随机编码解决方案
问题背景
需求是将序列号(整数,范围[0, 17576000))转换为形如AAA-nnn的唯一随机编码:
A为A-Z大写字母,n为0-9数字- 总共有
26^3 * 10^3 = 17,576,000种组合,本质是实现该区间内整数的唯一随机置换
此前尝试移位、加法、乘法、位运算等方法,要么超出范围,要么仅适用于2的幂次区间,无法满足要求;密码学PRP(伪随机置换)如AES-128、DES等针对的是2^64这类幂次范围,不匹配当前场景,且该需求仅用于游戏内分配炫酷编码,无需考虑安全性。
可行方案
1. 线性同余置换(简单高效)
用线性同余的变种实现区间内的唯一映射,核心公式:
encoded = (a * seq + b) % M
其中M = 17576000,需满足两个条件:
a与M互质(即两者最大公约数为1,比如选a=123457,可通过欧几里得算法验证)b为任意非负整数(比如b=98765)
解码时用逆运算:seq = ((encoded - b) * a_inv) % M,a_inv是a在模M下的逆元。
优势:计算极快,无需额外存储,完全保证唯一性,随机性足够游戏场景使用。
2. 分段预置换(直观可控)
把序列号拆成字母段和数字段,分别预先生成随机置换表,再组合编码:
- 字母段处理:序列号除以1000得到
letter_idx(范围0-17575),预先生成一个包含0-17575的随机打乱数组letter_perm,用letter_perm[letter_idx]作为置换后的索引,再转成3位大写字母。 - 数字段处理:序列号取模1000得到
num_idx(范围0-999),预先生成包含0-999的随机打乱数组num_perm,用num_perm[num_idx]作为置换后的数字,转成3位补零的数字串。 - 拼接结果:把字母串和数字串用
-连接,得到最终编码。
示例:
- 序列号
0→letter_idx=0,置换后为1234→ 转成BVC;num_idx=0,置换后为980→ 最终BVC-980 - 优势:置换表可提前生成并持久化,随机性直观可控,容易调整出“炫酷”的编码组合。
3. 哈希取模+冲突处理(不推荐)
用轻量哈希函数(如MurmurHash)对序列号计算哈希值,取模M得到编码值,若出现冲突则线性探测找空闲位置。但因为M规模不大,预置换表的方式效率更高,冲突处理反而增加复杂度,不推荐使用。
编码转换细节
以字母段转3位字母为例:
假设置换后的索引是x,计算:
x1 = x // (26*26) # 第一位字母的索引(0-25) x2 = (x // 26) % 26 # 第二位字母的索引 x3 = x % 26 # 第三位字母的索引
然后将每个索引转成对应字母:chr(x1 + ord('A')),以此类推得到3位字母串。
数字段转3位数字只需用格式化字符串:f"{perm_num_idx:03d}"。
内容的提问来源于stack exchange,提问作者LittleSaya
相关产品推荐
相关产品推荐

