排列计算器

算的是有序的选法:从 n 个不同元素里挑出 r 个并排成一列,先选谁、后选谁算不同结果,公式 A(n,r) = n!/(n-r)!。同屏给出结果、位数、溢出判定和同 n 下逐档改 r 的对照表,超过双精度整数范围自动改用 BigInt 精确计算。

nrA(n,r) 有序选法C(n,r) 无序对照位数双精度是否安全

提示:在任意输入框里按 Enter 即可计算。r 大于 n 会被拦下并说明原因,不会静默当成 n 处理。

使用方法

  1. 在「n(元素总数)」里填你手里的元素个数,示例填 10。允许 0 ~ 1000 的整数。
  2. 在「r(有序取出个数)」里填要取出并排序的个数,示例填 3。它可以等于 0,也可以等于 n,但不能大于 n。
  3. 点「计算」,或在任意输入框里按 Enter,结果区立刻给出 A(10,3) = 720,同时标出这个数的位数是 3 位、是否落在双精度安全区内。
  4. 想看「多取一个会翻多少倍」,点「加载更多」展开对照表,或直接改 r —— 表格里 r=2 是 90,r=3 是 720,r=4 是 5040,正好是 8 倍关系。
  5. 要拿去和「不区分顺序」的选法比,把同一组 n、r 的 C(n,r) 列一起看:示例里 C(10,3) = 120,正好是 720 除以 3! = 6。

这个排列计算器能解决什么问题

「从 n 个人里选 r 个」这句话在现实里其实有两种意思,而这两种意思的答案相差 r! 倍,这就是排列计算器存在的全部理由。

第一种是不区分顺序的:8 个人里挑 3 个人组队,先选谁后选谁不影响结果,答案是 C(8,3) = 56 种。第二种是区分顺序的:同样 8 个人选 3 个来颁发金、银、铜牌,先谁站上领奖台就是不同的结果,答案是 A(8,3) = 336 种。336 ÷ 56 = 6,正好是 3!。搞混这两个数,报名系统的名额统计、抽奖的排列组合、密码强度估算都会整体偏差一个量级。

本页具体处理四类问题:一是给定 n 与 r 得出有序选法的确切值;二是给出这个值的十进制位数,方便判断它能不能塞进数据库的整型列或前端安全整数;三是明确告诉你什么时候结果已经超出 double 能精确表示的范围,并自动换成 BigInt 算到底;四是把同 n 下逐档递增的 r 排成一张表,让你看出「多一个位置等于乘一个 (n−r+1)」这个规律,而不是每次重新算。整个排列计算器不含任何随机数,同样的输入永远得到同样的输出。

本页只算有序选法。如果你要求的是「选出来就行、不管谁在第几位」,那是组合,请用页面底部的组合计算器;如果你要的是 n! 本身这个数,则是阶乘,用阶乘计算器。本页在结果区会并排显示 C(n,r) 作为对照,但主结果永远是 A(n,r),不会把两者混在一起。

原理与规则说明

公式本身只有一行:A(n,r) = n! / (n-r)! = n × (n-1) × (n-2) × … × (n-r+1),一共 r 个因子。页面数据源里登记的表达式写的是阶乘比值 f(n)/f(n-r),数学上完全等价,但本页在实现上不按阶乘比值算,而是用右边的连乘形式。

为什么不用阶乘比值:阶乘比值需要先算出 n!,也就是做 n 次乘法,再除掉 (n-r)!。连乘只需 r 次。当 n=100、r=3 时,先算 100! 要 100 次乘法,连乘只要 3 次,省掉 97 次;当 n=1000、r=3 时省掉 997 次。更关键的是中间量的大小:算 1000! 时中间结果会冲破 double 的上限溢出成 Infinity,而连乘 1000×999×998 只有 3 个因子,最终值 997002000 稳稳落在安全区内。少算的那些因子不仅费时间,还在溢出路径上制造垃圾。

精度处理是本页最关键的一步。JavaScript 的 Number 是 IEEE 754 双精度浮点,能连续精确表示的整数上限是 Number.MAX_SAFE_INTEGER = 9007199254740991,也就是 253−1。超出这个值之后,末尾数字会被静默舍入 —— 不是报错,是给你一个看起来合理但错的数。本页的做法是:先用连乘在 BigInt 上算出精确值,再判断它是否超过 253−1;没超过就按数字显示,超过就在结果区额外挂一条提示,并改用千分位分组的长文本形式输出,保证每一位都可读、不可丢。

两个必须区分的阈值,别混为一谈,这一点决定了排列计算器什么时候必须换算法:

还有一个容易被忽略的中间量:位数。A(n,r) 的十进制位数决定了你能不能把它写进论文、写进数据库的 VARCHAR、或者塞进 Excel 单元格(上限 32767 字符)。本页把位数单独列一格,因为它是判断「这个结果还有没有实际用途」最快的指标。

遵循的规范:排列与组合的计数定义来自组合数学的标准表述,符号 A(n,r)(部分教材写 P(n,r))与 C(n,r) 并列;页面采用 IEEE 754-2019 定义的 binary64 交换格式来判定精度边界;大整数运算走 ECMAScript 2020 引入的 BigInt 类型,其语义在 ECMA-262 规范里定义为任意精度整数。三个来源都不是「最新政策」这类会变的东西。

完整示例(数值仅作演示)

示例条件:n = 10,r = 3。逐项算下来:

这组数字是闭合的:把 r 改成 2,对照表给 90,正好是 720 ÷ 8(因为 n−r+1 = 8);把 r 改成 5,给 30240 = 720 × 8 × 7,也对得上。上面正文的每个数字都能在下方对照表里找到同一行。 以上数值仅作演示,不代表任何真实场景的抽样结果。

输入范围与对照表

下表固定 n = 10,逐档列出 r 从 0 到 10 的结果,把 A(n,r) 与 C(n,r) 并排放,可以直接看出两者比值恒等于 r! 这个规律。表格默认显示 12 行,点「加载更多」展开全部 22 行,也可以导出成 CSV(带 BOM,Excel 直接打开不乱码)。当前输入的 n=10、r=3 那一行会高亮。

nrA(n,r) 有序选法C(n,r) 无序对照位数双精度是否安全
100111安全
10110102安全
10290452安全
1037201203安全
10450402104安全
105302402525安全
1061512002106安全
1076048001206安全
1081814400457安全
1093628800107安全
1010362880017安全
2051860480155047安全
201067044257280018475612安全
52531187520025989609安全
5213395424264391123968000063501355960022超上限
10039702001617006安全
10057528752075287528安全
10010628156509555294720001731030945644020超上限
100039970020001661670009安全

另一组容易混淆的对照:A(n,r) 与 C(n,r) 的比值恒等于 r!,但只在 r 固定时才成立。n=8、r=3 时 A=336、C=56、比值 6;n=8、r=8 时 A=40320、C=1、比值 40320。看表时务必按同一行比较,不要跨行对比比值。

输入范围、边界与精度说明

常见问题

A(n,r) 和 P(n,r) 是同一个东西吗?

是同一个排列数的两种记号。A 来自英文 Arrangement 的首字母,P 来自 Permutation。不同教材用不同字母,本页统一用 A,因为组合数固定写 C(n,r),配套好记。真正需要区分的是 A 与 C:前者管顺序,后者不管。

为什么组合计算器算出来的数总是我的结果除以 r!?

因为两者只差一个「顺序是否重要」。A(n,r) = C(n,r) × r!,r! 是把 r 个已经选好的元素重新排列的全排列数。如果你的场景里「先选 A 再选 B」和「先选 B 再选 A」是同一件事,那你需要的其实是 C(n,r),请用组合计算器。举例:8 个人里选 3 个组队,队伍成员不分先后,用 C(8,3) = 56;同样 8 个人选 3 个定金银铜牌,名次本身就是要输出的信息,用 A(8,3) = 336。

为什么结果突然变成很长一串数字,还带一条橙色提示?

因为结果超过了 9007199254740991(253−1),也就是 JavaScript 能精确表示的最大整数。再往上走,Number 类型会因为二进制尾数只有 53 位有效数字而把末尾舍入 —— 比如 3954242643911239680000 会被存成 3.95424264391124×1021,看起来只差最后几位,实际差的倍数是 44 万倍量级。本页检测到越界就改用 BigInt 重算,把完整每一位都给你。

r 填 0 为什么结果是 1,不是 0?

因为「什么都不取」只有一种取法 —— 空排列。这是组合数学里的约定,A(n,0) = C(n,0) = 1 对任何 n 都成立。所以 n=0 且 r=0 时结果是 1,不是报错;只有 r 大于 n 才是无定义。

n 最多只能填 1000,为什么不能再大?

两个原因。一是循环成本:A(n,r) 连乘要做 r 次乘法,n 封顶 1000 就意味着最坏情况 1000 次循环,再大页面会卡;二是内存:A(1000,1000) = 1000! 已经有 2568 位,继续往上结果位数增长极快,把它完整渲染到页面上没有实际意义。真要处理更大的 n,行业做法是改用对数口径(算 log 值再取指)只保留数量级,或者干脆用数学软件而不是网页。

我怎么知道填进去的数没被浏览器悄悄改掉?

看结果区「位数」那一格旁边有没有「超上限」标记。有标记说明结果已超出双精度精确范围,页面走的是 BigInt 路径,每一位都可读。另外本页所有输入都设了 min / max / step,浏览器原生校验会先拦一道越界和小数,JS 再判一次并给出具体是哪个字段、允许范围多大的中文提示,不会静默归零。

这个页面会把我填的 n 和 r 上传到哪吗?

哪也不去。全部计算就是一个 BigInt 连乘循环,加上一次和 9007199254740991 的比较,以及一次 1024 以内长度的整数转字符串,没有任何网络请求,也没有引入第三方库。你可以在开发者工具的 Network 面板里确认:页面加载完之后不会再发出任何请求,刷新一下输入也就没了。

我只想知道「有多少种可能」,不关心顺序,用这个页还是用别的?

用组合计算器。本页从头到尾算的都是有序选法,主结果永远是 A(n,r)。虽然结果区会并排给你 C(n,r) 作为对照,但那一列的用途是让你看清差了多少倍、差在 r! 上,不适合直接当答案抄走。另一个常被搞混的场合是「密码有多少种可能」:如果字符不能重复且位置有别,那是排列 A;如果允许重复且只看字符集,那是幂运算,两者都不是本页的公式。

相关工具