
用过 Excel 生成随机数的同学都知道,RAND、RANDBETWEEN、RANDARRAY 这类函数都属于易失性函数------只要对工作表做任何编辑(哪怕只是在空白单元格输入一个值),这些函数就会自动重算,随机结果直接改变。
比如老师想给学生随机分组,用公式=SORTBY(B5:B13,RANDARRAY(ROWS(B5:B13)))实现了随机排序,结果修改其他单元格时,分组结果反复变化,完全无法固定。
传统的解决办法是复制→选择性粘贴→数值,但这种方式会破坏原公式,想要重新生成随机结果又要重新写公式,步骤繁琐且低效。
而种子随机数生成器(Seeded RNG)就是解决这个问题的最优解:给一个种子值 ,生成固定的随机序列;更换种子值,生成新序列;相同种子值,永远返回相同结果,完美实现可复现的随机性。
本次我们基于 Park-Miller 算法 实现种子随机数,这是一种成熟的线性同余生成算法,核心逻辑是通过初始种子→乘法→取模的循环操作,生成伪随机整数,再归一化到 0~1 之间。
核心公式逻辑:
a=16807,模数m=2147483647(2^31-1,32 位有符号整数最大值);seed经过计算:MOD(a*seed, m),得到下一个随机整数;m,归一化得到 0~1 之间的随机小数;示例计算(种子=42):
=LET( seed,42, a,16807, m,2147483647, MOD(a*seed,m)) // 返回705894以 705894 为新种子,再次计算得到 1126542223,以此类推,最终除以 m 得到 0~1 的随机数。
Excel 的 LAMBDA 函数支持自定义可复用函数,结合 SCAN、LET 等函数,我们可以实现支持溢出输出 的种子随机数函数,并命名为RAND_SEQUENCE,最终实现传种子+生成数量,直接返回随机序列。
SCAN 函数的核心作用是累积计算并返回每一步结果,完美适配 Park-Miller 算法的循环种子生成逻辑,语法:
=SCAN([initial_value],array,lambda)利用 SEQUENCE 控制生成数量,SCAN 循环计算种子序列,示例公式:
=LET( seed,42, n,3, a,16807, m,2147483647, step,LAMBDA(s,_,MOD(a*s,m)), results,SCAN(seed,SEQUENCE(n),step), results/m) // 返回{705894/m;1126542223/m;1579310009/m}将上述公式封装为 LAMBDA 函数,把seed和n设为入参,实现可调用的基础版本:
=LAMBDA(seed,n, LET( a,16807, m,2147483647, step,LAMBDA(s,_,MOD(a*s,m)), results,SCAN(seed,SEQUENCE(n),step), results/m ))RAND_SEQUENCE;=RAND_SEQUENCE(42,3)。基础版本对种子值有要求(非 0、小于 m),添加种子归一化逻辑,避免非法种子导致的错误:
=LAMBDA(seed,n, LET( a,16807, m,2147483647, start,IF(INT(seed)=0,1,MOD(INT(seed),m)), step,LAMBDA(s,_,MOD(a*s,m)), results,SCAN(start,SEQUENCE(n),step), results/m ))基础版本仅支持整数种子,存在两个问题:
解决方案是实现自定义 HASH 函数 ,将字符串转换为大整数种子,既解决上述问题,又让种子更易记忆(如"apple"、"orange")。
采用经典的 DJB2 哈希算法,将字符串转换为 32 位整数,公式如下:
=LAMBDA(str, LET( s,TEXT(str,"@"), bytes,UNICODE(MID(s,SEQUENCE(LEN(s)),1)), h0,5381, step,LAMBDA(h,c,MOD(h*33+c,2^32)), REDUCE(h0,bytes,step) ))同样通过「名称管理器」注册为HASH,调用示例:
=HASH("apple") // 返回253337143=HASH("orange") // 返回319921761让 RAND_SEQUENCE 支持字符串种子,最终完整版公式:
=LAMBDA(seed,n, LET( a,16807, m,2147483647, h,HASH(seed), start,IF(INT(h)=0,1,MOD(INT(h),m)), step,LAMBDA(s,_,MOD(a*s,m)), results,SCAN(start,SEQUENCE(n),step), results/m ))此时可直接用字符串作为种子,调用更友好:
=RAND_SEQUENCE("apple",3) // 返回{0.710028;0.444729;0.560484}=RAND_SEQUENCE("orange",10) // 溢出输出10个随机数替代原生的 RANDARRAY,用 RAND_SEQUENCE 实现永不随意变化的随机排序,核心公式:

=LET( students,B3:B11, SORTBY(students,RAND_SEQUENCE(G3,ROWS(students))))核心优势:
无需手动重新注册 HASH 和 RAND_SEQUENCE,直接复制已有工作表即可实现函数复用:
uD83DuDCAC 写在最后
本文基于 Excel 的 LAMBDA 生态,实现了可复现、健壮性 的种子随机数生成器,彻底解决了原生随机函数易失性的痛点,适配随机分组、模拟、抽奖、数据洗牌等几乎所有需要稳定随机数的场景。
其实 Excel 的 LAMBDA 函数还能实现更多高级功能,比如自定义数据校验、批量处理、复杂数组计算等,完全可以把 Excel 打造成轻量级的无代码开发工具。
最后想问问大家:你在工作中是否遇到过 Excel 随机数乱变的问题?又是怎么解决的?还有哪些 LAMBDA 函数的高级用法想了解?欢迎在评论区留言交流~
",