Notes › Life Essays › Both Formulas Show Up, Only One Enters TDEE: parseInt Truncation, Two Rounding Rules and Three Hard-Coded Tiers on the 221-Line BMR Page

Both Formulas Show Up, Only One Enters TDEE: parseInt Truncation, Two Rounding Rules and Three Hard-Coded Tiers on the 221-Line BMR Page

The page prints 1,618 and 1617.5 side by side, yet only one multiplication in the 221-line template reaches TDEE: silent parseInt truncation, the cell layout of three rounding rules, a guard that skips the activity field, and a 30/40/30 back-calculation that matches none of 9 samples.

Both numbers show up, but only one reaches the ledger that follows

The page computes the moment it loads: under the default male/30/175/70/1.55 the big-number cell prints "1,649 kcal", the four statistics rows are 1,649, 1,696, ×1.55 and 2,556, and the last line of the formula card reads "1648.8 × 1.55 = 2555.6 kcal" -- the multiplicand is the Mifflin number, while 1695.7 only stands off to the side.

The only multiplication on the whole page is the tdee = bmrMifflin * activity at L135; the three tiers and the nine gram cells all derive from it, and Harris, once computed, simply stops at the display layer. The template is 221 lines / 10105 bytes; extracted into a pure Node probe it ran 8 five-value tuples: Harris came out higher every time, with a BMR-layer gap of 31.154 to 111.047 that multiplies through activity into 37.3848 to 191.556075 -- and not a single cell on the interface prints this layer.

The four bars for male/30/170/70/1.2 1617.5 1671.672 1941 2006.0064 M rule H rule Page TDEE If H rule Only the first three print: 1,618 / 1,672 / 1,941; the fourth is off by 65.00640000000003.

Figure 1: the dashed bar has no matching cell on the interface.

Three rulers: 1617.5 shows as "1,618" here but as "1617.5" there

  • 16 cells go through fmt (Math.round, then thousands separators): the big-number cell 1, the statistics rows 3, the tier figures 3, and the gram cells 9.
  • 3 cells go through fmt1 (toFixed(1), no thousands separators): all of them sit on the formula card.
  • 2 places are bare concatenation: the activity-factor row and the factor inside the formula card's equation.

The same number therefore takes two looks on one screen: for male/30/170/70 the 1617.5 prints as "1,618" on the statistics row and "1617.5" on the formula card; for male/30/250/300 the 4417.5 prints as "4,418" and "4417.5". That 0.5 is a difference between the rulers, not a second calculation.

Rounding examples: Math.round(0.5)=1; Math.round(-0.5)=-0, yet fmt outputs "-0" while the bare concatenation of the same value gives "0"; Math.round(-1617.5)=-1617, .5 rounds toward +∞; fmt1(1648.75)="1648.8" against fmt1(1.005)="1.0".

Cells per ruler: 16 / 3 / 2 fmt 16 cells fmt1 3 cells Raw 2 spots The same 1617.5: fmt prints 1,618, fmt1 prints 1617.5.

Figure 2: which cells each of the three rulers handles.

parseInt only sits in the age cell

Among L108 to L111 only the age goes through parseInt, while the other three cells use parseFloat. "25.9" and "25abc" are all read as 25 with no warning at all, and the big-number cell echoes back 1,477: under female/170/70/1.2 the truncated Mifflin is 1476.5, the untruncated arithmetic is 1472, a gap of 4.5, and after multiplying by 1.2 into TDEE it is 1771.8 against 1766.3999999999999, a gap of 5.4. The same string "1e2" is read as 1 in the age box (the mifflin cell shows 1,597) and read as 100 in the weight box by parseFloat (1,752). Only "abc", "-3", "0" and an empty string trigger the invalid-parameter toast, and before the return the screen is not cleared, so the previous round's "1,618" stays on it.

The guard does not check the activity cell

L113 only tests isNaN and ≤0 across those three cells. When the dropdown is broken into "x" or an empty string, parseFloat yields NaN: under male/30/170/70 the Mifflin row 1,618 and the Harris row 1,672 still print as usual, the factor row bare-concatenates "×NaN", and the TDEE row plus the three tiers and the nine gram cells -- 12 cells in total -- all become "—", while the formula card writes "1617.5 × NaN = — kcal" and no toast fires. Typing "Infinity" for weight is a second silent path: every check lets it through, and the big-number cell goes straight to "— kcal".

-500, +300 and 30/40/30: the constants are written all the way down

The three tiers are generated by L138 to L140, so under any input the two neighbouring tiers always differ by 500 and 300, head to tail by 800. The macronutrient split is the 0.30, 0.40, 0.30 at L144 to L150; the weights sum to exactly 1, so the back-calculation before rounding equals the target, and the default middle tier's raw 2555.5625 is restored verbatim.

But the gram figures on the interface go through fmt, so the assumption that the gap comes from fmt1 does not hold. Back-calculating from the interface grams at 4/4/9, none of the 9 samples equals the target: the default group's low tier 2055.5625 shows 154/206/69 and back-calculates to 2061, off by +5.4375; female/40/160/55/1.55's middle tier 1842.95 shows 138/184/61 and back-calculates to 1837, off by -5.9500000000000455. All nine gaps fall within -5.95 to +5.4375, against a theoretical bound of 0.5×4+0.5×4+0.5×9=8.5.

Gender recognizes only three letters, and the gap between the two formulas can flip sign

L120 and L178 share one test, gender === 'male': 'MALE', an empty string and null all fall into the -161 branch -- under male/30/170/70/1.2 the "MALE" value puts 1,452 in the mifflin cell, the same as "female", and only the all-lowercase spelling gives 1,618. The constant gap between the two branches is 5-(-161)=166; on the Harris side it is not constant, since at 30/170/70 the value 1671.672 against 1491.643 differs by 180.029.

The ordering even flips with weight, and the 8 tuples just happen to sit on the same side: under male/170/30, at w=50 the H-M figure is -13.768000000000029 and at w=55 it is +3.2170000000000982, with a critical point of 54.052987930526946; for female/170/30 the direction reverses, at w=124 the value is -0.5190000000002328, with a critical point of 123.31075697211145.

A quick look at the copy

The dropdown's 5 values are 1.2/1.375/1.55/1.725/1.9, and the ×figures in the option text match those values row by row; checked against the 12 items in tools.php the verdict is [match] 7, [conflict] 1, [partial] 4, and the conflicting one is the intro's unit-toggle note (ft/lb), for which the markup has no matching control. Where the two formulas come from is covered in that earlier article on the site, so it is not repeated here; the page itself lives in the BMR calculator.

FAQ

Q: Both numbers are printed on the page, so why does only one feed the ledger?

There is only one multiplication, and its multiplicand is hardcoded to Mifflin; both of Harris's display positions sit before it, and the 37.3848 to 191.556075 you would owe by swapping the multiplicand has no cell to carry it.

Q: Two neighbouring cells differ by 0.5 -- is the number computed twice?

Once, with two rulers: 1617.5 through fmt gives "1,618", and through fmt1 gives "1617.5".

Q: The three gram figures added back at 4/4/9 do not reach the target cell?

Not adding back is the norm: none of the 9 samples match, the gaps lie within -5.95 to +5.4375, and after each of the three cells passes a Math.round the rounding difference is amplified by 4, 4 and 9, staying inside the bound of 8.5.

📎 Related articles

Upper-Casing .ß Adds One Slot to the Whole Line: Three Tiers Measured Line by Line on an 18-Line Sample 2026-11-09 Which three of the four switches default to on: collapse rules, first-seen representatives and the dedupe short circuit 2026-11-08 It Took Three Presses to Reach Grandma: 36 Kinship Rules and 11,110 Chains Measured 2026-11-07 How Many Problems Fit on One A4 Worksheet Page: Font Size, Margins and the Info Bar Rewrite the Pagination 2026-11-03 The Same 23 Bytes at Four Error-Correction Levels: How Far This Page's Own QR Encoder Goes 2026-10-30