Notes › Resources › 15 sheet-music PDFs dragged into the File Info page: the largest lands 876.8 KB, short of the next tier by 150729 bytes, and the average size rounds twice

15 sheet-music PDFs dragged into the File Info page: the largest lands 876.8 KB, short of the next tier by 150729 bytes, and the average size rounds twice

Dragging 15 public-domain sheet-music PDFs onto the File Info page fills the size column with KB only, the largest sitting 150729 bytes short of the next tier. Displayed strings restore with an absolute drift of 350 bytes, the average size rounds twice, and the export follows drop order.

15 sheet-music PDFs land on the File Info page and the size column has complaints

The whole thing started as plain archiving: two public-domain scores, 15 PDF files in all, and I only wanted their names and sizes copied into one table, so I dropped the entire batch onto the File Info page. The stats bar answered with Total files: 15 / Total size: 5.06 MB / Average size: 345.4 KB. Yet in the 15 rows listed underneath, not a single cell in the size column carried an MB unit, and even the smallest file never dropped into the byte tier either. Two unit systems were speaking on one screen.

The page under test is the File Info Reader: the template weighs 11104 bytes across 275 line breaks with CRLF 0, the script block spans 6860 bytes and 167 lines beginning at line 108, and its 10 functions were carried verbatim into a plain Node probe, pulled back through toString and matched character by character. The thresholds were never edited and Math.round was never removed.

Three thresholds, two precisions, no rollover at the ceiling

The entire size column is decided by one helper, formatSize, living at lines 162-167. It holds three thresholds - 1024, 1048576 and 1073741824 - prints the KB tier through toFixed(1), and the MB and GB tiers through toFixed(2), while the lowest byte tier is concatenated as-is at line 163 without a single decimal of rounding. The table below pins down what each boundary prints.

Input bytesDisplayed stringBehavior
10231023 Bbyte tier, no rounding
10241.0 KBrollover keeps one decimal
10485751024.0 KBat the ceiling, no rollover
10485761.00 MBrollover keeps two decimals
10737418231024.00 MBat the ceiling, no rollover
10737418241.00 GBthe third tier
1023.91023.9 Bdecimal tail copied verbatim

Every one of my 15 files sits between 1024 and 1048576, so the whole column runs through toFixed(1). The smallest, at 42286 bytes, prints 41.3 KB with 41262 bytes still to travel before the lower bound; the largest, at 897847 bytes, prints 876.8 KB and misses the tier change by 150729 bytes, roughly 147.2 KB. Zero files land in the MB tier and zero in the byte tier. The store copy promises automatic conversion among KB, MB and GB, yet this batch delivers only the middle rung: the GB branch never fires, and what silently falls out of view is the bottom byte tier together with the two-decimal precision that should have come with it.

Turning the displayed strings back into bytes: an absolute drift of 350

Multiply each printed value back at its own tier - the KB numbers times 1024 - and reconcile the reconstruction against the bytes measured on disk. The true total is 5305582; the reconstructed total is 5305548.8, a net drift of -33.2 bytes. The sum of the per-file absolute drifts, however, comes to 350 bytes, and the worst single file is off by -48: 149552 displays as 146.0 KB and reconstructs to 149504.

  • 88176 becomes 86.1 KB becomes 88166.4, off by -9.6
  • 814854 becomes 795.8 KB becomes 814899.2, off by +45.2
  • 897847 becomes 876.8 KB becomes 897843.2, off by -3.8

The net drift stays as small as 33.2 only because positive and negative errors cancel each other; 350 is how much this column really erases once signs are taken seriously. The pair 63004 and 62934 is the stingiest case: two different files, both displayed as 61.5 KB, both reconstructing to the same 62976, indistinguishable on screen.

Reconciliation across 4 samples (whole column in the KB tier) Real bytes Displayed string Restored bytes Delta 42286 41.3 KB 42291.2 +5.2 149552 146.0 KB 149504 -48.0 814854 795.8 KB 814899.2 +45.2 897847 876.8 KB 897843.2 -3.8

Figure 1: the round trip from displayed strings back to bytes, worst single file -48 bytes.

The average size is rounded twice, and only crafted samples reveal it

The stats bar takes the three steps written at lines 227-229: totalSize accumulates the raw bytes directly, avgSize equals Math.round(totalSize / total), and that integer is then handed to formatSize again - two rounds of rounding inside a single display. For the 12 Schubert files, totalSize measures 5141254 and the true average is 428437.8333333333; the round step turns it into 428438, a shift of 0.16666666668606922 bytes, and the screen prints 418.4 KB. Delete Math.round entirely and the screen still prints 418.4 KB, because that shift is far too small to move the formatted string; in this batch the second rounding is completely invisible.

Making the double rounding show its face means building samples on purpose. Take 5 files sharing 5376 bytes: the true average is 1075.2, the rounded integer drives the page to write 1.0 KB, while skipping the round step leaves the raw value to print 1.1 KB - reality differs by only 0.2, yet the display jumps a whole decimal step. Or take 4 files sharing 401 bytes: the average is 100.25; because the byte tier performs no toFixed at all, the rounded version writes 100 B and the unrounded version writes 100.25 B. The asymmetry explains when the artifact can appear: the KB tier moves in steps of 0.1 KB, which equals 102.4 bytes, so the fractional bytes shaved off by the first rounding can only flip the printed string when the true average sits right on one of those swap lines.

MB and KB share one screen inside the stat lines

Each stat line feeds its own value into its own formatSize call, so the units split apart right in front of the reader. The Schubert folder reads Total size: 4.90 MB alongside Average size: 418.4 KB; the combined drop of all 15 files reads 5.06 MB alongside 345.4 KB; only Schumann's three files keep both lines inside KB, 160.5 KB next to 53.5 KB. The combined total 5305582 is exactly 5141254 plus 164328, closing against the file-by-file sum with nothing left over. That closure also proves what was actually measured: I dragged the PDFs only, the little sidecar text files living in those directories never entered the batch, so the readouts are net sums of the dragged set. Had the whole directories, 5161096 and 172148 bytes together, been dropped instead, the totals would have printed as 4.92 MB and 168.1 KB.

Fixed totalSize 5141254, only the file count n changes File count n Average line Total size line Same tier? 2 2.45 MB 4.90 MB Same tier 4 1.23 MB 4.90 MB Same tier 5 1004.2 KB 4.90 MB Mixed from here 12 418.4 KB 4.90 MB This batch's real reading

Figure 2: the same 5141254 again; moving n from 4 to 5 pushes the average line into another unit while the total line refuses to budge.

The two showcase fields on the resource pages read "PDF 4.90 MB" and "PDF 0.16 MB", a display convention rounded to two decimals rather than measured bytes, and the gap between those two accounts is not small. The 12 files behind the public-domain Schubert Lieder score sum to 5141254 bytes net when measured directly, while 4.90 MB reconstructs to 5138022.4, off by -3231.6 bytes - same tier, different string - and off by -23073.6 bytes against the whole-directory figure 5161096. The 3 files behind the public-domain Schumann Kinderscenen score sum to 164328 bytes net and this page writes 160.5 KB, yet 0.16 MB reconstructs to 167772.16, off by +3444.16 bytes and crossing a tier boundary on the way; the published display value and the measured byte count are not the same quantity.

Q: Can a displayed size cell be reversed back into the original bytes?

Only down to the precision the display kept. Across the 15 files the reconstructed total is 5305548.8 while the true total is 5305582, a net difference of -33.2 bytes, and the largest single-file gap reaches -48 bytes.

Q: Why does the total size print in MB while the average prints in KB?

Because the two lines never share a unit decision; each hands its own value to formatSize, and the tier follows the magnitude of that value. Keep one fixed totalSize 5141254 and raise the file count from 4 to 5: the average line slides from 1.23 MB down to 1004.2 KB while the total line stays in MB the whole time.

Q: Is the double rounding of the average normally invisible?

In ordinary folders, yes. The shift from 428437.8333333333 to 428438 never reaches the toFixed(1) string-swap line, so deleting Math.round still leaves 418.4 KB on screen. Only the crafted pair 1075.2 and 100.25, built to sit right on a swap boundary, pulls the two rounding passes apart.

Q: If I sort the table and then export, does the exported file keep the sorted order?

No. The export walks the drop order, and sorting only rearranges the table's on-screen copy. Measured directly: the table shows 01_SchumannOp15No01-a4.pdf as its first row while the exported file begins with 01_einsamkeit-a4.pdf.

📎 Related articles

Two Public-Domain Classics Merged into 555733 Bytes: the Panel Reads 2334 Lines and 187299 Characters, and Each Separator Tier Adds Its Own Slots 2026-11-13 Two Whole Public-Domain Classics Fed into the Text Reader: Line Counts at 81474 and 78497 Bytes, the Code Unit and Code Point Gap, and the GBK Misread Replacement-Character Bill 2026-11-12 Three Hash Implementations on One Page: Two Public-Domain TXTs as Byte Corpus, Measuring the Block Ledger and Encoding Mutations of file-md5 Character by Character 2026-11-09 Shenglü Qimen and Liweng Duiyun Fed Whole Into the Text Diff Page: 154 Common Lines, 665 Added, 401 Removed, and the Stats Line Gives Only Two Numbers 2026-11-08 Measuring a Pinyin Table With Liweng Duiyun: 7160 Hits, 21 Off-Table Chars, 232 Polyphones 2026-11-07