Notes › Tech Notes › Both Tabs Recompute the Same C(n,r): n=20 Writes Out 40 Factors, n=21 Writes None, a 300-Digit Result and Two Readings of r=0

Both Tabs Recompute the Same C(n,r): n=20 Writes Out 40 Factors, n=21 Writes None, a 300-Digit Result and Two Readings of r=0

One factorial division written twice on the combination calculator: 10 of 12 pairs match the big-number cell verbatim while 2 differ by branch; the expansion row shows only up to n=20 yet results still compute, and each tab reads r=0 differently.

The same division, written twice on one page

It started with a number I wanted to check. On the compute tab of the combination page I entered n=15 and r=7, and the big-number cell returned 6,435. Switching to the generate-all tab and filling 15 elements from E1 through E15, the cell again read 6,435. Only after pasting this page template (9838 bytes / 236 lines) verbatim into Node and running it around did the picture clear up: line L120 on the compute side and line L207 on the generate side hold a literally isomorphic statement, factorialBig(n) / (factorialBig(r) * factorialBig(n - r)), so one value gets computed twice; add the recursion count of combos and the statistics-line wording, and a single (n,r) pair has three sources to reconcile.

I cross-tested 12 identical (n,r) pairs. In 10 of them the big-number cell strings match character for character, down to the comma shape of 6,435. The other 2 disagree, and neither is an arithmetic slip: both are branch differences. The pair (20,10) hits the 15-element gate and the cell stays at the markup default 「—」; for (7,0) the compute side prints 「1」, while the generate side silently rewrites r<1 to 1, so what it actually evaluates is C(7,1) and the cell shows 「7」. That gap is the reading difference between the two tabs of the combination calculator.

(n, r)Compute tabGenerate tab
(8, 3)5656
(15, 7)6,4356,435
(20, 10)184,756—
(7, 0)17

The expansion has a switch, the result does not

The guard at L130, if (n <= 20), only encloses the expansion line itself. Among the 231 cells with 0≤r≤n≤20, a measured 231 carry an expansion row; among the 1660 cells with n=21..60, not a single one shows any expansion, yet the very same cell (21,10) still hands over its result 352,716. The term count of the whole expansion follows r alone, never n: holding r=3 fixed, the five cells n=3, 5, 10, 15, 20 all show three numerator terms plus three denominator terms, six factors in total, and only the full string grows slowly from 25 to 28 characters; the moment n reaches 21, those six factors vanish together.

The most terms belong to (20,20): 20 numerator factors over 20 denominator factors, an expansion row written full with 40 factors across 183 characters, and the computed answer is simply 1. The runner-up cell (20,19) carries 38 factors over 174 characters, with the result 20.

Fixed r=3: the 6 expanded factors never change with n n = 3 6 factors 25 chars Result 1 n = 15 6 factors n = 5 6 factors 25 chars Result 10 n = 20 6 factors n = 10 6 factors 26 chars Result 120 n = 21 expansion gone Most terms, (20,20): 40 factors over 183 characters, result 1 Runner-up, (20,19): 38 factors over 174 characters, result 20

Figure 1: expansion term counts and full-string characters for five values of n at fixed r=3, plus the two cells where the term count caps out.

The symmetry sentence is real copy, but three full factorials still get computed

On the very screen where L150 displays 「利用对称性简化计算」, L120 still computes factorialBig(20), factorialBig(19) and factorialBig(1) as three complete factorials; measured, factorialBig(20) = 2432902008176640000, 19 digits long. The expansion row still writes out its full 38 factors, and nowhere on the page is there any min(r, n-r) reduction. The factorial accounts themselves live on another page: the factorial calculator.

The big-number side: exact division never leaves a remainder, commas follow a formula

Sweeping all 1891 cells of 0≤r≤n≤60 and taking the remainder cell by cell gives 0 cells with a non-zero remainder - the division at L120 is BigInt integer division without rounding protection, and inside this range it never truncates. The longest line, C(1000,500), comes out 300 digits, and fmtBig (L99) inserts 99 thousands-separator commas into it; the rule comma count = floor((digits-1)/3) holds cell by cell across the whole table. For reference, Number.MAX_SAFE_INTEGER = 9007199254740991 (16 digits). One extra double-precision comparison sits off the page code path: the first divergence lands at n=55, r=27, the exact value 3824345300380220 against the double reading 3824345300380219.5. The digit-by-digit accounts are not recomputed here; the older article already lists the table: the BigInt factorial article.

Digits versus the commas fmtBig inserts C(20,10) 6 digits 1 comma 184,756 C(50,25) 15 digits 4 commas 126,410,606,437,752 C(100,50) 30 digits 9 commas C(1000,500) 300 digits 99 commas commas = floor((digits-1)/3)

Figure 2: digit counts and comma counts for four results, with the commas aligned cell by cell to that formula across the whole table.

Two readings of r=0, and why invisible does not mean cleared

On the compute tab the three rows 5/0, 0/0 and 20/0 all pass every guard and print 「1」; the expansion row degenerates into the literal 「() / ()」, 7 characters with 0 digits inside. An edge like 0≤0 does not take the early return, because r > n is false there. The generate tab behaves entirely differently: L184 silently rewrites r<1, and across five inputs for r - 「0」, 「-1」, 「abc」, the empty string, and "1.9" - there is no toast, the statistics line uniformly says 「每个组合取:1 个」, and every cell shows 「4」.

The two early returns of the hidden panels (L110 and L114) differ only in whether that one toast fires; measured, neither clears the cells: the previous round's 56 and all 4 formula lines stay behind. Being invisible is not the same as being emptied. The inputs also set no max - comb-n and comb-r carry min="0", comb-gen-r carries min="1", and the JS side has no upper gate (isFinite and Infinity appear 0 times in this template), so n=1000 with r=500 prints 300 digits straight away.

One tab switch buys one extra computation

Line L86 inside switchMode recomputes on the side. Measured: calling the generate function 200 times with 6 elements and r=3 leaves exactly 1 deduplicated state, "20:20:0" - combos is a constant inside the function, reopened on every call, so clicking more never accumulates anything. Running calcComb twice on the same input returns a formula string 407 characters long, byte for byte identical. Switching to the generate tab moves the cell from 「—」 to 「6」.

The accounts for the code itself

The script body measures 6607 bytes over 159 lines; the markup holds 13 ids in total and 27 occurrences of the math-* class; all 7 functions read back from context match the template source verbatim, the longest, generateCombinations, running 2532 characters. The list column keeps one older account of its own: a display cap of 5000 rows.

Q: Do the two tabs always print the same number?

Not always. The same division is written twice, and in 10 of 12 pairs the big-number cells match verbatim; but (20,10) leaves the generate side parked at 「—」, and (7,0) shows 「1」 on one side and 「7」 on the other. Every difference comes from branching, never from the formula. Matching here means only that the big-number cell strings are character-identical; rendering and performance are not covered.

Q: Why does n=21 lose the expansion steps?

The n <= 20 at L130 only controls whether the expansion row shows; the result is computed either way. The 352,716 for (21,10) still comes out - the screen simply loses the two visible rows of numerator and denominator fragments.

Q: What does r=0 actually compute?

It depends on the tab. The compute side treats it as legal and prints 1; the generate side, via L184, turns it into 1, so what you get is C(n,1). Same r=0, two readings.

📎 Related articles

Star Run Length Is Hardcoded: the Masking Page Cuts a Fixed 4, 3, 11 or 12 Stars, an 18-Unit String Is Taken by the Phone Tier, an Empty Box Falls Back to * 2026-11-13 The Lock Is One-Way and Percent Is Two Rulers: pct 50 Gives 619x430, and All Four PNG Quality Stops Return 6971 B 2026-11-13 A Month on This Page Is Hard-Coded as 30 Days: the Six Fixed Divisors, 13-Digit Millisecond Input, and slice(0,16) Truncation Measured Under UTC+8 and UTC-5 2026-11-13 Eight elements compute 40320 permutations but list only 5000 rows: two unrelated caps on the permutation page, duplicates counted by 3!, and the process break at n above 20 2026-11-12 Assembly Order and Case Folding for Ad Links: Six UTM States, Two Hard Caps and Five Panel Fields on Their Own Scales 2026-11-12