杂记 › 技术笔记 › 8 个元素算得出 40320 条却只列 5000 行:排列计算器的两道互不相干的上限、重复元素按 3! 计数与 n≤20 的过程断点

8 个元素算得出 40320 条却只列 5000 行:排列计算器的两道互不相干的上限、重复元素按 3! 计数与 n≤20 的过程断点

排列数算得出 40320 条,列表只写 5000 行:两道互不相干的闸、重复元素按 n! 出条数、n≤20 才给展开与约分、调用点 0 处的死函数,全在字符串层实测。

40320 条与 5000 行同屏

元素框里敲 8 个单字母,「排列总数」栏写着 40,320,列表拉到底只有 5000 行,尾行补一句「共 40320 种排列,仅显示前 5000 种」。把 permutation.html(实测 233 行 / 9158 字节)逐字摘进纯 Node 探针跑一圈才发现,它有两把互不相干的尺:一把管算数,一把管往屏上写几行,而中间那台生成排列的机器不认「元素长得一样」。

两道闸各判各的

L177 的 if (n > 8) 判的是切分之后的元素个数:9 项以上四组原文得到同一句 toast「元素数量超过 8 个,排列数过多,请减少元素」,且这道 return 在 heap 之前,列表长度为 0。

L215 的 maxShow = Math.min(perms.length, 5000) 判的却是显示行数,perms 在内存里始终满着:n=7 实生 5040、只写 5000 行、藏 40 条,n=8 实生 40320、同样只写 5000 行、藏 35320 条。5000 落在 720 与 5040 之间,9 档里只有 2 档撞尾行。测的这一页是排列计算器。

元素个数 → 实生条数 → 写到屏上的行数 n = 6 720 720 尾行不出现 n = 7 5040 5000 藏 40 淡色实生 5040,深色写出 5000 n = 8 40320 5000 藏 35320、12.4008% n = 5:120 → 120 行

图 1:同一批 n 档上,实生条数与显示行数各是多少。

heap 只按下标交换

heap 全程按 k 的奇偶交换两枚下标,从不比较元素值,所以重复元素按 n! 出条数:A, A, B 出 6 行、去重 3 条;A, A, A 出 6 行且全同、去重 1;甲 / 甲 / 乙 也是 6 行 3 条。界面两处(总数栏与「n! =」统计行)都写 n!,不写不重复条数;批量 40 组原文里去重数小于写出行数的有 11 组。这些都只是这一页的行为,推不出「这类工具都这样」。

实生 / 去重 / 露在前 5000 行里 A, A, B 6 行 3 条 全部可见 A, A, B, C, D, E, F, G 40320 行 20160 条 前 5000 行里 2520 种 A, A, A, A, B, B, B, B 40320 行 70 种 前 5000 行里 35 种

图 2:界面那个数与两本真实的账。

展开与约分只在 n ≤ 20 给

L136 那道 if (n <= 20) 决定过程面板给几行:n=5,r=3 给 4 行,n=20,r=7 仍 4 行且约分行 7 个因子、结果 390,700,800;n=21,r=1 起只剩 3 行,展开与约分整段换成一行「结果」(n=22,r=22 同)。约分行的因子个数恒等于 r,r=0 时那一格写成「约分: = 1」。

generate 侧没有这道分支:calc 对 n 没上限,n=100000、r=2 照样给 9,999,900,000,只是耗时 9553.75 ms。阶乘本身在阶乘计算那页。

分隔正则先替你改了 n

L170 的字符类 /[,、\s,\n]+/ 把两种逗号、顿号、换行连空白类一起当分隔。New York, 北京 因此解析成 3 个元素,界面按 3!=6 报条数,而用户想的是 2 个;反过来 A;B 只切出 1 个元素——全角分号不在字符类里,半角分号、竖线、连字符同样不分。

两条静默路径分开:trim 后为空走 L164,原文只由分隔符组成时 n 为 0、走 L173,两者都是面板隐藏、无 toast、总数栏没被写过。L173 不是死代码,一个逗号就命中。

fmt 是调用点 0 处的死函数

词边界正则数下来,fmt 只命中 L102 的定义、调用点 0 处,fmtBig 命中 6 处,显示全走 BigInt 串。Number 那把尺躺着,却藏不住两处分界:写法分界在 22!,它写作 1.1240007277776077e+21 而值仍精确;精度分界在 23!,BigInt 口径 25852016738884976640000、回读 double 得 25852016738884978212864,是两个不同的数。

onclick 是拼出来的

L218 把 join 后的元素串塞进单引号实参,只转义单引号。字符串层两条实测:元素含单引号时属性串是 copyItem(this, 'A\', B'),解析这段 JS 得回 A', B,与该行可见文本去掉行号前缀后相同;元素含双引号时,onclick 的值在第一个双引号处就闭合,属性正则只能取到 copyItem(this, 'A 这半截;元素含小于号时该字符原样进 innerHTML,浏览器解析成什么未实测。

两套口径分开:innerHTML 注入后的结构、toast 呈现与 2500 ms、复制反馈与按钮文字 1500 ms 复原、type=number 把 5.7 与 1e3 写进 value 什么、渲染 2019032 字节列表串要多久,本批未开浏览器,一律标未实测。字符串这侧能说:n=8 时列表里 onclick 片段数是 5000,第 40320 条没有复制入口——节点不存在。

切回去一定重跑

L82 切回哪侧重跑哪侧:切回 calc 后结果栏是按 n=12、r=2 重算的 132,不是切走前的 60;r 大于 n 时函数在写 textContent 之前就 return,节点留着旧串而 display 已是 none,generate 侧换成 9 项后那 2019012 字符一字未清。

15 条文案判定

config/tools.php 第 885 行起该条目与模板两枚 hint 逐条判:一致 7、冲突 2、部分一致 6。

文案实测判定
每个排列可复制n=8 时列表只有 5000 个可点条目,另 35320 条无入口冲突
从 n 个不同元素中取出 r 个不校验互不相同,A, A, B 按 3!=6 计冲突
最多支持 8 个元素(8! = 40320 种排列)8 与 40320 成立,5000 没写进任何文案部分一致

5000 在模板里命中 3 处(L215、L220、L221)全在代码里,5040 命中 0 处,唯一露出它的是尾行,且不带千分位,与同屏的 40,320 两种写法。排列与组合的概念区分旧文排列与组合讲过,不重讲。

Q:那 40320 到底算错没有?

没算错。40,320 既是 factorialBig(8),也是 8 个元素实生的 perms.length;误会只在把总数栏当成行数——屏上停在 5000 行,另 35320 条还在内存里,没有出口。

Q:有重复元素时怎么只留一条?

这一页没有去重开关,两处都写 n!。字符串层的折算是 n! 除以各值出现次数之阶乘的积:A,A,B,C,D,E,F,G 由 40320 折成 20160,那一档在前 5000 行里只露出 2520 种。

Q:切一下 tab 结果就变了,是没保存吗?

是重跑不是丢失:切回必按当前输入再算一次,非法输入只藏面板、不覆写旧串,于是「隐藏但残留」。

📎 相关文章

投放链接的装配顺序与大小写折叠:UTM 生成器六态标注、两道硬上限与五栏各用一把尺实测 2026-11-12 13格算法表与7道验签闸门:JWT 工具页验签侧的分支比解码侧更窄,逐算法真签真验矩阵 2026-11-12 拖到 4 和拖到 8,屏幕上都是 43890 个块:马赛克预览与导出的两套块网格、三档会崩与 6px 误触阈值 2026-11-10 位图进 SVG 只换了个盒子:232 字节容器常数、一个从不生效的「base64 嵌入」勾选,与四档缩放下纹丝不动的 142064 个字符 2026-11-10 转完悄悄少了 271 个字符:Markdown 转 HTML 的洞协议、64 轮回填与 20 条提示上限 2026-11-10