Macro Calculator
Accurately calculate your daily calories (TDEE) and macro targets (protein, fat, carbs) based on science-backed formulas. Mobile-first, accessible macro calculator for fat loss, muscle gain, or maintenance.
Full original guide (expanded)
Skip to main contentMacro Calculator
This interactive macro calculator estimates your daily energy needs (TDEE) and translates them into practical protein, fat, and carbohydrate targets. It’s built for anyone optimizing nutrition for fat loss, muscle gain, or maintenance, using peer‑reviewed equations and accessible, mobile‑first design.
Calculator
Macro settings
Results
Data Source and Methodology
- Mifflin MD, St Jeor ST, et al. A new predictive equation for resting energy expenditure in healthy individuals. American Journal of Clinical Nutrition 1990;51(2):241–247. DOI
- Katch VL, McArdle WD. Nutrition, Weight Control, and Exercise. Houghton Mifflin; 1993. (Katch–McArdle BMR: BMR = 370 + 21.6 × LBM[kg])
- Activity multipliers adapted from FAO/WHO/UNU Expert Consultation on Human Energy Requirements (2001) and common sports nutrition practice.
- Protein guidance synthesized from Morton RW et al., Br J Sports Med. 2018;52:376–384. DOI
Tutti i calcoli si basano rigorosamente sulle formule e sui dati forniti da questa fonte.
The Formula Explained
BMR (Mifflin–St Jeor):
For men: \( \mathrm{BMR} = 10W + 6.25H - 5A + 5 \)
For women: \( \mathrm{BMR} = 10W + 6.25H - 5A - 161 \)
BMR (Katch–McArdle): \( \mathrm{BMR} = 370 + 21.6 \times \mathrm{LBM} \)
where \( \mathrm{LBM} = W \times (1 - \frac{\%BF}{100}) \)
Total Daily Energy Expenditure (TDEE): \( \mathrm{TDEE} = \mathrm{BMR} \times \mathrm{Activity} \)
Goal calories: \( \mathrm{Calories}_{target} = \mathrm{TDEE} \times (1 + r) \) where r is goal rate (e.g., −0.20)
Macros:
\( P_{g} = p \times \text{kg basis} \), \( F_{g} = \begin{cases} \frac{f\% \times \mathrm{Calories}}{9} & (\%) \\ f_{kg}\times \text{kg basis} & (\mathrm{g/kg})\end{cases} \)
\( C_{g} = \frac{\mathrm{Calories} - 4P_{g} - 9F_{g}}{4} \)
Glossary of Variables
- W: Body weight in kilograms (kg).
- H: Height in centimeters (cm).
- A: Age in years.
- %BF: Body fat percentage.
- LBM: Lean body mass (kg).
- BMR: Basal Metabolic Rate (kcal/day).
- TDEE: Total Daily Energy Expenditure (kcal/day).
- r: Goal rate as a fraction (e.g., −0.2 = 20% deficit).
- P_g, F_g, C_g: Protein, fat, carbohydrate grams per day.
- p: Protein in g/kg (basis: body weight or lean mass).
- f%: Fat as percent of calories. f_kg: Fat in g/kg.
How It Works: A Step-by-Step Example
Inputs: Male, 30 years, 180 cm, 80 kg, 15% body fat, activity 1.55, goal −20%, protein 1.8 g/kg (total body weight), fat 25% calories.
- BMR (MSJ): 10×80 + 6.25×180 − 5×30 + 5 = 1780 kcal/day.
- TDEE: 1780 × 1.55 = 2759 kcal/day.
- Target calories: 2759 × (1 − 0.20) = 2207 kcal/day.
- Protein: 1.8 × 80 = 144 g (576 kcal).
- Fat: 25% × 2207 = 551.8 kcal → 61.3 g.
- Carbs: (2207 − 576 − 551.8) / 4 = 269.8 g.
Frequently Asked Questions (FAQ)
Do I need my body fat percentage?
No. If you don’t know it, use Mifflin–St Jeor. If you have a good estimate, Katch–McArdle can personalize BMR via lean mass.
What if my carbs calculate as negative?
Reduce protein or fat targets, or increase total calories. Very high protein plus high fat at low calories can leave no room for carbs.
How fast should I lose or gain?
Common guidance: lose 0.25–1.0% body weight per week; gain 0.25–0.5% to minimize fat gain. Adjust the goal percentage accordingly.
Are activity multipliers accurate for athletes?
They are averages. Endurance or physically demanding jobs may require higher multipliers. Use weight trends to calibrate.
Should protein be based on lean mass or total weight?
If body fat is high or known, lean-mass basis can be more appropriate. Otherwise, total body weight basis is fine.
Is fiber included?
This calculator targets total carbohydrates. Aim for 25–35 g/day of fiber from whole foods for health and satiety.
Can I export or print results?
Copy the results into your notes or a meal-planning tool. A print-friendly layout is supported by your browser.
Formula (LaTeX) + variables + units
','
= sel => Array.from(document.querySelectorAll(sel)); const clamp = (v, min, max) => Math.max(min, Math.min(max, v)); const toNumber = (v) => { const n = Number(v); return Number.isFinite(n) ? n : NaN; }; const formatKcal = n => isFinite(n) ? Math.round(n).toLocaleString() + ' kcal' : '—'; const formatGrams = n => isFinite(n) ? Math.round(n) + ' g' : '—'; const inchesFromFtIn = (ft, inch) => (ft*12 + inch); const cmFromInches = inches => inches * 2.54; const kgFromLb = lb => lb * 0.45359237; const lbFromKg = kg => kg / 0.45359237; // Elements const ageEl = $('#age'); const heightCmEl = $('#heightCm'); const heightFtEl = $('#heightFt'); const heightInEl = $('#heightIn'); const weightKgEl = $('#weightKg'); const weightLbEl = $('#weightLb'); const bodyFatEl = $('#bodyFat'); const unitsMetricEl = $('#unitsMetric'); const unitsImperialEl = $('#unitsImperial'); const heightMetricGroup = $('#heightMetricGroup'); const heightImperialGroup = $('#heightImperialGroup'); const weightMetricGroup = $('#weightMetricGroup'); const weightImperialGroup = $('#weightImperialGroup'); const eqMSJ = $('#eqMSJ'); const eqKM = $('#eqKM'); const equationNote = $('#equationNote'); const activityEl = $('#activity'); const proteinPerKgEl = $('#proteinPerKg'); const proteinBasisEl = $('#proteinBasis'); const proteinMirrorEl = $('#proteinMirror'); const fatMethodEl = $('#fatMethod'); const fatPercentEl = $('#fatPercent'); const fatPerKgEl = $('#fatPerKg'); const goalRateEl = $('#goalRate'); const goalCustomEl = $('#goalCustom'); const errors = { age: $('#ageError'), height: $('#heightError'), heightImp: $('#heightImpError'), weight: $('#weightError'), weightImp: $('#weightImpError'), bodyFat: $('#bodyFatError'), activity: $('#activityError'), goal: $('#goalError'), }; const outputs = { bmr: $('#bmrOut'), act: $('#activityOut'), tdee: $('#tdeeOut'), cal: $('#calorieOut'), protein: $('#proteinOut'), fat: $('#fatOut'), carbs: $('#carbOut') }; // Tooltips
('input[name="goal"]').forEach(r => r.addEventListener('change', () => { syncGoalUI(); compute(); })); goalRateEl.addEventListener('change', () => compute()); goalCustomEl.addEventListener('input', () => compute()); syncGoalUI(); // Fat method UI function syncFatUI(){ const method = fatMethodEl.value; if (method === 'percent') { fatPercentEl.hidden = false; fatPerKgEl.hidden = true; } else { fatPercentEl.hidden = true; fatPerKgEl.hidden = false; } } fatMethodEl.addEventListener('change', () => { syncFatUI(); compute(); }); fatPercentEl.addEventListener('input', compute); fatPerKgEl.addEventListener('input', compute); syncFatUI(); // Protein mirror to per-lb for clarity function updateProteinMirror(){ const perKg = toNumber(proteinPerKgEl.value); if (!isFinite(perKg)) { proteinMirrorEl.textContent = '—'; return; } const perLb = perKg / 2.2046226218; // g/kg to g/lb proteinMirrorEl.textContent = '≈ ' + (Math.round(perLb*100)/100).toFixed(2) + ' g/lb basis'; } proteinPerKgEl.addEventListener('input', () => { updateProteinMirror(); compute(); }); proteinBasisEl.addEventListener('change', compute); updateProteinMirror(); // Validation helpers function setError(el, msg, key){ el.setAttribute('aria-invalid', 'true'); if (key && errors[key]) errors[key].textContent = msg; } function clearError(el, key){ el.removeAttribute('aria-invalid'); if (key && errors[key]) errors[key].textContent = ''; } // Field-level validation (on blur) ageEl.addEventListener('blur', () => { const v = toNumber(ageEl.value); if (!isFinite(v) || v < 10 || v > 100) setError(ageEl, 'Please enter an age between 10 and 100.', 'age'); else clearError(ageEl, 'age'); }); heightCmEl.addEventListener('blur', () => { const v = toNumber(heightCmEl.value); if (!isFinite(v) || v < 120 || v > 230) setError(heightCmEl, 'Height must be between 120 and 230 cm.', 'height'); else clearError(heightCmEl, 'height'); }); heightFtEl.addEventListener('blur', () => { const ft = toNumber(heightFtEl.value), inch = toNumber(heightInEl.value); if (!isFinite(ft) || !isFinite(inch) || ft < 4 || ft > 7 || inch < 0 || inch > 11) setError(heightFtEl, 'Enter a valid height between 4’0” and 7’11”.', 'heightImp'); else clearError(heightFtEl, 'heightImp'); }); heightInEl.addEventListener('blur', () => { const ft = toNumber(heightFtEl.value), inch = toNumber(heightInEl.value); if (!isFinite(ft) || !isFinite(inch) || ft < 4 || ft > 7 || inch < 0 || inch > 11) setError(heightInEl, 'Enter a valid height between 4’0” and 7’11”.', 'heightImp'); else clearError(heightInEl, 'heightImp'); }); weightKgEl.addEventListener('blur', () => { const v = toNumber(weightKgEl.value); if (!isFinite(v) || v < 30 || v > 300) setError(weightKgEl, 'Weight must be between 30 and 300 kg.', 'weight'); else clearError(weightKgEl, 'weight'); }); weightLbEl.addEventListener('blur', () => { const v = toNumber(weightLbEl.value); if (!isFinite(v) || v < 66 || v > 660) setError(weightLbEl, 'Weight must be between 66 and 660 lb.', 'weightImp'); else clearError(weightLbEl, 'weightImp'); }); bodyFatEl.addEventListener('blur', () => { const v = toNumber(bodyFatEl.value); if (bodyFatEl.value === '') { clearError(bodyFatEl, 'bodyFat'); return; } if (!isFinite(v) || v < 3 || v > 60) setError(bodyFatEl, 'Enter body fat between 3% and 60%, or leave empty.', 'bodyFat'); else clearError(bodyFatEl, 'bodyFat'); }); activityEl.addEventListener('blur', () => { const v = toNumber(activityEl.value); if (!isFinite(v) || v < 1.1 || v > 2.5) setError(activityEl, 'Please select a valid activity level.', 'activity'); else clearError(activityEl, 'activity'); }); // Equation note when Katch requires BF% function checkEquationRequirement(){ if (eqKM.checked) { const bf = toNumber(bodyFatEl.value); if (!isFinite(bf)) { equationNote.textContent = 'Katch–McArdle requires a valid body fat percentage.'; } else { equationNote.textContent = ''; } } else { equationNote.textContent = ''; } } eqMSJ.addEventListener('change', () => { checkEquationRequirement(); compute(); }); eqKM.addEventListener('change', () => { checkEquationRequirement(); compute(); }); bodyFatEl.addEventListener('input', () => { checkEquationRequirement(); compute(); }); // Input events -> compute [ageEl, heightCmEl, heightFtEl, heightInEl, weightKgEl, weightLbEl, activityEl].forEach(el => { el.addEventListener('input', compute); });
('input[name="units"]').forEach(el => el.addEventListener('change', () => { applyUnitsUI(); compute(); })); function getInputs(){ const metric = unitsMetricEl.checked; const sex = (document.querySelector('input[name="sex"]:checked')||{}).value || 'male'; const age = toNumber(ageEl.value); const activity = toNumber(activityEl.value); const equation = eqKM.checked ? 'km' : 'msj'; let heightCm, weightKg; if (metric) { heightCm = toNumber(heightCmEl.value); weightKg = toNumber(weightKgEl.value); } else { const ft = toNumber(heightFtEl.value); const inch = toNumber(heightInEl.value); const inches = inchesFromFtIn(ft, inch); heightCm = cmFromInches(inches); weightKg = kgFromLb(toNumber(weightLbEl.value)); } const bf = bodyFatEl.value === '' ? NaN : toNumber(bodyFatEl.value); // Goal rate const goal = (document.querySelector('input[name="goal"]:checked') || {}).value || 'maintain'; let rate = 0; if (goal === 'custom') { const custom = toNumber(goalCustomEl.value); rate = isFinite(custom) ? clamp(custom, -40, 40) / 100 : 0; if (!isFinite(custom)) errors.goal.textContent = 'Enter a custom percentage between −40 and +40.'; else errors.goal.textContent = ''; } else { rate = toNumber(goalRateEl.value); } // Macros const pPerKg = toNumber(proteinPerKgEl.value); const pBasis = proteinBasisEl.value; // 'tbw' or 'lbm' const fatMethod = fatMethodEl.value; const fatPercent = toNumber(fatPercentEl.value); const fatPerKg = toNumber(fatPerKgEl.value); return { metric, sex, age, heightCm, weightKg, bf, activity, equation, goal, rate, pPerKg, pBasis, fatMethod, fatPercent, fatPerKg }; } function compute(){ const inp = getInputs(); // Basic validity const validAge = isFinite(inp.age) && inp.age >= 10 && inp.age <= 100; const validH = isFinite(inp.heightCm) && inp.heightCm >= 120 && inp.heightCm <= 230; const validW = isFinite(inp.weightKg) && inp.weightKg >= 30 && inp.weightKg <= 300; const validAct = isFinite(inp.activity) && inp.activity >= 1.1 && inp.activity <= 2.5; if (!validAge || !validH || !validW || !validAct) { outputs.bmr.textContent = '—'; outputs.tdee.textContent = '—'; outputs.act.textContent = '—'; outputs.cal.textContent = '—'; outputs.protein.textContent = '—'; outputs.fat.textContent = '—'; outputs.carbs.textContent = '—'; return; } // BMR let bmr = NaN; if (inp.equation === 'msj') { const s = (inp.sex === 'male') ? 5 : -161; bmr = 10*inp.weightKg + 6.25*inp.heightCm - 5*inp.age + s; } else { const bf = toNumber(inp.bf); if (isFinite(bf)) { const lbm = inp.weightKg * (1 - bf / 100); bmr = 370 + 21.6 * lbm; } else { outputs.bmr.textContent = '—'; outputs.tdee.textContent = '—'; outputs.act.textContent = '—'; outputs.cal.textContent = '—'; outputs.protein.textContent = '—'; outputs.fat.textContent = '—'; outputs.carbs.textContent = '—'; return; } } const tdee = bmr * inp.activity; const targetCalories = tdee * (1 + inp.rate); // Protein grams let kgBasis = inp.weightKg; if (inp.pBasis === 'lbm') { if (isFinite(inp.bf)) { kgBasis = inp.weightKg * (1 - inp.bf / 100); } else { // fall back to TBW if no BF% kgBasis = inp.weightKg; } } const proteinG = Math.max(0, inp.pPerKg * kgBasis); // Fat grams let fatG = 0; if (inp.fatMethod === 'percent') { const pct = clamp(isFinite(inp.fatPercent) ? inp.fatPercent : 25, 5, 80) / 100; fatG = (targetCalories * pct) / 9; } else { const perKg = clamp(isFinite(inp.fatPerKg) ? inp.fatPerKg : 0.8, 0.2, 3.0); fatG = perKg * kgBasis; } // Carbs grams const remainingKcal = targetCalories - (proteinG * 4) - (fatG * 9); const carbsG = Math.max(0, remainingKcal / 4); // Output outputs.bmr.textContent = formatKcal(bmr); outputs.act.textContent = inp.activity.toFixed(2); outputs.tdee.textContent = formatKcal(tdee); outputs.cal.textContent = formatKcal(targetCalories); outputs.protein.textContent = formatGrams(proteinG); outputs.fat.textContent = formatGrams(fatG); outputs.carbs.textContent = formatGrams(carbsG); } // Initial compute compute(); // Footer dates const y = new Date().getFullYear(); const review = new Date(); $('#year').textContent = y; $('#reviewDate').textContent = review.toLocaleDateString(undefined, { year:'numeric', month:'long', day:'numeric' }); // Keyboard accessibility for radio "cards"
BMR (Mifflin–St Jeor): For men: \( \mathrm{BMR} = 10W + 6.25H - 5A + 5 \) For women: \( \mathrm{BMR} = 10W + 6.25H - 5A - 161 \) BMR (Katch–McArdle): \( \mathrm{BMR} = 370 + 21.6 \times \mathrm{LBM} \) where \( \mathrm{LBM} = W \times (1 - \frac{\%BF}{100}) \) Total Daily Energy Expenditure (TDEE): \( \mathrm{TDEE} = \mathrm{BMR} \times \mathrm{Activity} \) Goal calories: \( \mathrm{Calories}_{target} = \mathrm{TDEE} \times (1 + r) \) where r is goal rate (e.g., −0.20) Macros: \( P_{g} = p \times \text{kg basis} \), \( F_{g} = \begin{cases} \frac{f\% \times \mathrm{Calories}}{9} & (\%) \\ f_{kg}\times \text{kg basis} & (\mathrm{g/kg})\end{cases} \) \( C_{g} = \frac{\mathrm{Calories} - 4P_{g} - 9F_{g}}{4} \)
- No variables provided in audit spec.
- Health and Fitness — calcdomain.com · Accessed 2026-01-19
https://calcdomain.com/health-fitness - DOI — doi.org · Accessed 2026-01-19
https://doi.org/10.1093/ajcn/51.2.241 - DOI — doi.org · Accessed 2026-01-19
https://doi.org/10.1136/bjsports-2017-097608
Last code update: 2026-01-19
- Initial audit spec draft generated from HTML extraction (review required).
- Verify formulas match the calculator engine and convert any text-only formulas to LaTeX.
- Confirm sources are authoritative and relevant to the calculator methodology.
Macro Calculator
This interactive macro calculator estimates your daily energy needs (TDEE) and translates them into practical protein, fat, and carbohydrate targets. It’s built for anyone optimizing nutrition for fat loss, muscle gain, or maintenance, using peer‑reviewed equations and accessible, mobile‑first design.
Calculator
Macro settings
Results
Data Source and Methodology
- Mifflin MD, St Jeor ST, et al. A new predictive equation for resting energy expenditure in healthy individuals. American Journal of Clinical Nutrition 1990;51(2):241–247. DOI
- Katch VL, McArdle WD. Nutrition, Weight Control, and Exercise. Houghton Mifflin; 1993. (Katch–McArdle BMR: BMR = 370 + 21.6 × LBM[kg])
- Activity multipliers adapted from FAO/WHO/UNU Expert Consultation on Human Energy Requirements (2001) and common sports nutrition practice.
- Protein guidance synthesized from Morton RW et al., Br J Sports Med. 2018;52:376–384. DOI
Tutti i calcoli si basano rigorosamente sulle formule e sui dati forniti da questa fonte.
The Formula Explained
BMR (Mifflin–St Jeor):
For men: \( \mathrm{BMR} = 10W + 6.25H - 5A + 5 \)
For women: \( \mathrm{BMR} = 10W + 6.25H - 5A - 161 \)
BMR (Katch–McArdle): \( \mathrm{BMR} = 370 + 21.6 \times \mathrm{LBM} \)
where \( \mathrm{LBM} = W \times (1 - \frac{\%BF}{100}) \)
Total Daily Energy Expenditure (TDEE): \( \mathrm{TDEE} = \mathrm{BMR} \times \mathrm{Activity} \)
Goal calories: \( \mathrm{Calories}_{target} = \mathrm{TDEE} \times (1 + r) \) where r is goal rate (e.g., −0.20)
Macros:
\( P_{g} = p \times \text{kg basis} \), \( F_{g} = \begin{cases} \frac{f\% \times \mathrm{Calories}}{9} & (\%) \\ f_{kg}\times \text{kg basis} & (\mathrm{g/kg})\end{cases} \)
\( C_{g} = \frac{\mathrm{Calories} - 4P_{g} - 9F_{g}}{4} \)
Glossary of Variables
- W: Body weight in kilograms (kg).
- H: Height in centimeters (cm).
- A: Age in years.
- %BF: Body fat percentage.
- LBM: Lean body mass (kg).
- BMR: Basal Metabolic Rate (kcal/day).
- TDEE: Total Daily Energy Expenditure (kcal/day).
- r: Goal rate as a fraction (e.g., −0.2 = 20% deficit).
- P_g, F_g, C_g: Protein, fat, carbohydrate grams per day.
- p: Protein in g/kg (basis: body weight or lean mass).
- f%: Fat as percent of calories. f_kg: Fat in g/kg.
How It Works: A Step-by-Step Example
Inputs: Male, 30 years, 180 cm, 80 kg, 15% body fat, activity 1.55, goal −20%, protein 1.8 g/kg (total body weight), fat 25% calories.
- BMR (MSJ): 10×80 + 6.25×180 − 5×30 + 5 = 1780 kcal/day.
- TDEE: 1780 × 1.55 = 2759 kcal/day.
- Target calories: 2759 × (1 − 0.20) = 2207 kcal/day.
- Protein: 1.8 × 80 = 144 g (576 kcal).
- Fat: 25% × 2207 = 551.8 kcal → 61.3 g.
- Carbs: (2207 − 576 − 551.8) / 4 = 269.8 g.
Frequently Asked Questions (FAQ)
Do I need my body fat percentage?
No. If you don’t know it, use Mifflin–St Jeor. If you have a good estimate, Katch–McArdle can personalize BMR via lean mass.
What if my carbs calculate as negative?
Reduce protein or fat targets, or increase total calories. Very high protein plus high fat at low calories can leave no room for carbs.
How fast should I lose or gain?
Common guidance: lose 0.25–1.0% body weight per week; gain 0.25–0.5% to minimize fat gain. Adjust the goal percentage accordingly.
Are activity multipliers accurate for athletes?
They are averages. Endurance or physically demanding jobs may require higher multipliers. Use weight trends to calibrate.
Should protein be based on lean mass or total weight?
If body fat is high or known, lean-mass basis can be more appropriate. Otherwise, total body weight basis is fine.
Is fiber included?
This calculator targets total carbohydrates. Aim for 25–35 g/day of fiber from whole foods for health and satiety.
Can I export or print results?
Copy the results into your notes or a meal-planning tool. A print-friendly layout is supported by your browser.
Formula (LaTeX) + variables + units
','
= sel => Array.from(document.querySelectorAll(sel)); const clamp = (v, min, max) => Math.max(min, Math.min(max, v)); const toNumber = (v) => { const n = Number(v); return Number.isFinite(n) ? n : NaN; }; const formatKcal = n => isFinite(n) ? Math.round(n).toLocaleString() + ' kcal' : '—'; const formatGrams = n => isFinite(n) ? Math.round(n) + ' g' : '—'; const inchesFromFtIn = (ft, inch) => (ft*12 + inch); const cmFromInches = inches => inches * 2.54; const kgFromLb = lb => lb * 0.45359237; const lbFromKg = kg => kg / 0.45359237; // Elements const ageEl = $('#age'); const heightCmEl = $('#heightCm'); const heightFtEl = $('#heightFt'); const heightInEl = $('#heightIn'); const weightKgEl = $('#weightKg'); const weightLbEl = $('#weightLb'); const bodyFatEl = $('#bodyFat'); const unitsMetricEl = $('#unitsMetric'); const unitsImperialEl = $('#unitsImperial'); const heightMetricGroup = $('#heightMetricGroup'); const heightImperialGroup = $('#heightImperialGroup'); const weightMetricGroup = $('#weightMetricGroup'); const weightImperialGroup = $('#weightImperialGroup'); const eqMSJ = $('#eqMSJ'); const eqKM = $('#eqKM'); const equationNote = $('#equationNote'); const activityEl = $('#activity'); const proteinPerKgEl = $('#proteinPerKg'); const proteinBasisEl = $('#proteinBasis'); const proteinMirrorEl = $('#proteinMirror'); const fatMethodEl = $('#fatMethod'); const fatPercentEl = $('#fatPercent'); const fatPerKgEl = $('#fatPerKg'); const goalRateEl = $('#goalRate'); const goalCustomEl = $('#goalCustom'); const errors = { age: $('#ageError'), height: $('#heightError'), heightImp: $('#heightImpError'), weight: $('#weightError'), weightImp: $('#weightImpError'), bodyFat: $('#bodyFatError'), activity: $('#activityError'), goal: $('#goalError'), }; const outputs = { bmr: $('#bmrOut'), act: $('#activityOut'), tdee: $('#tdeeOut'), cal: $('#calorieOut'), protein: $('#proteinOut'), fat: $('#fatOut'), carbs: $('#carbOut') }; // Tooltips
('input[name="goal"]').forEach(r => r.addEventListener('change', () => { syncGoalUI(); compute(); })); goalRateEl.addEventListener('change', () => compute()); goalCustomEl.addEventListener('input', () => compute()); syncGoalUI(); // Fat method UI function syncFatUI(){ const method = fatMethodEl.value; if (method === 'percent') { fatPercentEl.hidden = false; fatPerKgEl.hidden = true; } else { fatPercentEl.hidden = true; fatPerKgEl.hidden = false; } } fatMethodEl.addEventListener('change', () => { syncFatUI(); compute(); }); fatPercentEl.addEventListener('input', compute); fatPerKgEl.addEventListener('input', compute); syncFatUI(); // Protein mirror to per-lb for clarity function updateProteinMirror(){ const perKg = toNumber(proteinPerKgEl.value); if (!isFinite(perKg)) { proteinMirrorEl.textContent = '—'; return; } const perLb = perKg / 2.2046226218; // g/kg to g/lb proteinMirrorEl.textContent = '≈ ' + (Math.round(perLb*100)/100).toFixed(2) + ' g/lb basis'; } proteinPerKgEl.addEventListener('input', () => { updateProteinMirror(); compute(); }); proteinBasisEl.addEventListener('change', compute); updateProteinMirror(); // Validation helpers function setError(el, msg, key){ el.setAttribute('aria-invalid', 'true'); if (key && errors[key]) errors[key].textContent = msg; } function clearError(el, key){ el.removeAttribute('aria-invalid'); if (key && errors[key]) errors[key].textContent = ''; } // Field-level validation (on blur) ageEl.addEventListener('blur', () => { const v = toNumber(ageEl.value); if (!isFinite(v) || v < 10 || v > 100) setError(ageEl, 'Please enter an age between 10 and 100.', 'age'); else clearError(ageEl, 'age'); }); heightCmEl.addEventListener('blur', () => { const v = toNumber(heightCmEl.value); if (!isFinite(v) || v < 120 || v > 230) setError(heightCmEl, 'Height must be between 120 and 230 cm.', 'height'); else clearError(heightCmEl, 'height'); }); heightFtEl.addEventListener('blur', () => { const ft = toNumber(heightFtEl.value), inch = toNumber(heightInEl.value); if (!isFinite(ft) || !isFinite(inch) || ft < 4 || ft > 7 || inch < 0 || inch > 11) setError(heightFtEl, 'Enter a valid height between 4’0” and 7’11”.', 'heightImp'); else clearError(heightFtEl, 'heightImp'); }); heightInEl.addEventListener('blur', () => { const ft = toNumber(heightFtEl.value), inch = toNumber(heightInEl.value); if (!isFinite(ft) || !isFinite(inch) || ft < 4 || ft > 7 || inch < 0 || inch > 11) setError(heightInEl, 'Enter a valid height between 4’0” and 7’11”.', 'heightImp'); else clearError(heightInEl, 'heightImp'); }); weightKgEl.addEventListener('blur', () => { const v = toNumber(weightKgEl.value); if (!isFinite(v) || v < 30 || v > 300) setError(weightKgEl, 'Weight must be between 30 and 300 kg.', 'weight'); else clearError(weightKgEl, 'weight'); }); weightLbEl.addEventListener('blur', () => { const v = toNumber(weightLbEl.value); if (!isFinite(v) || v < 66 || v > 660) setError(weightLbEl, 'Weight must be between 66 and 660 lb.', 'weightImp'); else clearError(weightLbEl, 'weightImp'); }); bodyFatEl.addEventListener('blur', () => { const v = toNumber(bodyFatEl.value); if (bodyFatEl.value === '') { clearError(bodyFatEl, 'bodyFat'); return; } if (!isFinite(v) || v < 3 || v > 60) setError(bodyFatEl, 'Enter body fat between 3% and 60%, or leave empty.', 'bodyFat'); else clearError(bodyFatEl, 'bodyFat'); }); activityEl.addEventListener('blur', () => { const v = toNumber(activityEl.value); if (!isFinite(v) || v < 1.1 || v > 2.5) setError(activityEl, 'Please select a valid activity level.', 'activity'); else clearError(activityEl, 'activity'); }); // Equation note when Katch requires BF% function checkEquationRequirement(){ if (eqKM.checked) { const bf = toNumber(bodyFatEl.value); if (!isFinite(bf)) { equationNote.textContent = 'Katch–McArdle requires a valid body fat percentage.'; } else { equationNote.textContent = ''; } } else { equationNote.textContent = ''; } } eqMSJ.addEventListener('change', () => { checkEquationRequirement(); compute(); }); eqKM.addEventListener('change', () => { checkEquationRequirement(); compute(); }); bodyFatEl.addEventListener('input', () => { checkEquationRequirement(); compute(); }); // Input events -> compute [ageEl, heightCmEl, heightFtEl, heightInEl, weightKgEl, weightLbEl, activityEl].forEach(el => { el.addEventListener('input', compute); });
('input[name="units"]').forEach(el => el.addEventListener('change', () => { applyUnitsUI(); compute(); })); function getInputs(){ const metric = unitsMetricEl.checked; const sex = (document.querySelector('input[name="sex"]:checked')||{}).value || 'male'; const age = toNumber(ageEl.value); const activity = toNumber(activityEl.value); const equation = eqKM.checked ? 'km' : 'msj'; let heightCm, weightKg; if (metric) { heightCm = toNumber(heightCmEl.value); weightKg = toNumber(weightKgEl.value); } else { const ft = toNumber(heightFtEl.value); const inch = toNumber(heightInEl.value); const inches = inchesFromFtIn(ft, inch); heightCm = cmFromInches(inches); weightKg = kgFromLb(toNumber(weightLbEl.value)); } const bf = bodyFatEl.value === '' ? NaN : toNumber(bodyFatEl.value); // Goal rate const goal = (document.querySelector('input[name="goal"]:checked') || {}).value || 'maintain'; let rate = 0; if (goal === 'custom') { const custom = toNumber(goalCustomEl.value); rate = isFinite(custom) ? clamp(custom, -40, 40) / 100 : 0; if (!isFinite(custom)) errors.goal.textContent = 'Enter a custom percentage between −40 and +40.'; else errors.goal.textContent = ''; } else { rate = toNumber(goalRateEl.value); } // Macros const pPerKg = toNumber(proteinPerKgEl.value); const pBasis = proteinBasisEl.value; // 'tbw' or 'lbm' const fatMethod = fatMethodEl.value; const fatPercent = toNumber(fatPercentEl.value); const fatPerKg = toNumber(fatPerKgEl.value); return { metric, sex, age, heightCm, weightKg, bf, activity, equation, goal, rate, pPerKg, pBasis, fatMethod, fatPercent, fatPerKg }; } function compute(){ const inp = getInputs(); // Basic validity const validAge = isFinite(inp.age) && inp.age >= 10 && inp.age <= 100; const validH = isFinite(inp.heightCm) && inp.heightCm >= 120 && inp.heightCm <= 230; const validW = isFinite(inp.weightKg) && inp.weightKg >= 30 && inp.weightKg <= 300; const validAct = isFinite(inp.activity) && inp.activity >= 1.1 && inp.activity <= 2.5; if (!validAge || !validH || !validW || !validAct) { outputs.bmr.textContent = '—'; outputs.tdee.textContent = '—'; outputs.act.textContent = '—'; outputs.cal.textContent = '—'; outputs.protein.textContent = '—'; outputs.fat.textContent = '—'; outputs.carbs.textContent = '—'; return; } // BMR let bmr = NaN; if (inp.equation === 'msj') { const s = (inp.sex === 'male') ? 5 : -161; bmr = 10*inp.weightKg + 6.25*inp.heightCm - 5*inp.age + s; } else { const bf = toNumber(inp.bf); if (isFinite(bf)) { const lbm = inp.weightKg * (1 - bf / 100); bmr = 370 + 21.6 * lbm; } else { outputs.bmr.textContent = '—'; outputs.tdee.textContent = '—'; outputs.act.textContent = '—'; outputs.cal.textContent = '—'; outputs.protein.textContent = '—'; outputs.fat.textContent = '—'; outputs.carbs.textContent = '—'; return; } } const tdee = bmr * inp.activity; const targetCalories = tdee * (1 + inp.rate); // Protein grams let kgBasis = inp.weightKg; if (inp.pBasis === 'lbm') { if (isFinite(inp.bf)) { kgBasis = inp.weightKg * (1 - inp.bf / 100); } else { // fall back to TBW if no BF% kgBasis = inp.weightKg; } } const proteinG = Math.max(0, inp.pPerKg * kgBasis); // Fat grams let fatG = 0; if (inp.fatMethod === 'percent') { const pct = clamp(isFinite(inp.fatPercent) ? inp.fatPercent : 25, 5, 80) / 100; fatG = (targetCalories * pct) / 9; } else { const perKg = clamp(isFinite(inp.fatPerKg) ? inp.fatPerKg : 0.8, 0.2, 3.0); fatG = perKg * kgBasis; } // Carbs grams const remainingKcal = targetCalories - (proteinG * 4) - (fatG * 9); const carbsG = Math.max(0, remainingKcal / 4); // Output outputs.bmr.textContent = formatKcal(bmr); outputs.act.textContent = inp.activity.toFixed(2); outputs.tdee.textContent = formatKcal(tdee); outputs.cal.textContent = formatKcal(targetCalories); outputs.protein.textContent = formatGrams(proteinG); outputs.fat.textContent = formatGrams(fatG); outputs.carbs.textContent = formatGrams(carbsG); } // Initial compute compute(); // Footer dates const y = new Date().getFullYear(); const review = new Date(); $('#year').textContent = y; $('#reviewDate').textContent = review.toLocaleDateString(undefined, { year:'numeric', month:'long', day:'numeric' }); // Keyboard accessibility for radio "cards"
BMR (Mifflin–St Jeor): For men: \( \mathrm{BMR} = 10W + 6.25H - 5A + 5 \) For women: \( \mathrm{BMR} = 10W + 6.25H - 5A - 161 \) BMR (Katch–McArdle): \( \mathrm{BMR} = 370 + 21.6 \times \mathrm{LBM} \) where \( \mathrm{LBM} = W \times (1 - \frac{\%BF}{100}) \) Total Daily Energy Expenditure (TDEE): \( \mathrm{TDEE} = \mathrm{BMR} \times \mathrm{Activity} \) Goal calories: \( \mathrm{Calories}_{target} = \mathrm{TDEE} \times (1 + r) \) where r is goal rate (e.g., −0.20) Macros: \( P_{g} = p \times \text{kg basis} \), \( F_{g} = \begin{cases} \frac{f\% \times \mathrm{Calories}}{9} & (\%) \\ f_{kg}\times \text{kg basis} & (\mathrm{g/kg})\end{cases} \) \( C_{g} = \frac{\mathrm{Calories} - 4P_{g} - 9F_{g}}{4} \)
- No variables provided in audit spec.
- Health and Fitness — calcdomain.com · Accessed 2026-01-19
https://calcdomain.com/health-fitness - DOI — doi.org · Accessed 2026-01-19
https://doi.org/10.1093/ajcn/51.2.241 - DOI — doi.org · Accessed 2026-01-19
https://doi.org/10.1136/bjsports-2017-097608
Last code update: 2026-01-19
- Initial audit spec draft generated from HTML extraction (review required).
- Verify formulas match the calculator engine and convert any text-only formulas to LaTeX.
- Confirm sources are authoritative and relevant to the calculator methodology.
Macro Calculator
This interactive macro calculator estimates your daily energy needs (TDEE) and translates them into practical protein, fat, and carbohydrate targets. It’s built for anyone optimizing nutrition for fat loss, muscle gain, or maintenance, using peer‑reviewed equations and accessible, mobile‑first design.
Calculator
Macro settings
Results
Data Source and Methodology
- Mifflin MD, St Jeor ST, et al. A new predictive equation for resting energy expenditure in healthy individuals. American Journal of Clinical Nutrition 1990;51(2):241–247. DOI
- Katch VL, McArdle WD. Nutrition, Weight Control, and Exercise. Houghton Mifflin; 1993. (Katch–McArdle BMR: BMR = 370 + 21.6 × LBM[kg])
- Activity multipliers adapted from FAO/WHO/UNU Expert Consultation on Human Energy Requirements (2001) and common sports nutrition practice.
- Protein guidance synthesized from Morton RW et al., Br J Sports Med. 2018;52:376–384. DOI
Tutti i calcoli si basano rigorosamente sulle formule e sui dati forniti da questa fonte.
The Formula Explained
BMR (Mifflin–St Jeor):
For men: \( \mathrm{BMR} = 10W + 6.25H - 5A + 5 \)
For women: \( \mathrm{BMR} = 10W + 6.25H - 5A - 161 \)
BMR (Katch–McArdle): \( \mathrm{BMR} = 370 + 21.6 \times \mathrm{LBM} \)
where \( \mathrm{LBM} = W \times (1 - \frac{\%BF}{100}) \)
Total Daily Energy Expenditure (TDEE): \( \mathrm{TDEE} = \mathrm{BMR} \times \mathrm{Activity} \)
Goal calories: \( \mathrm{Calories}_{target} = \mathrm{TDEE} \times (1 + r) \) where r is goal rate (e.g., −0.20)
Macros:
\( P_{g} = p \times \text{kg basis} \), \( F_{g} = \begin{cases} \frac{f\% \times \mathrm{Calories}}{9} & (\%) \\ f_{kg}\times \text{kg basis} & (\mathrm{g/kg})\end{cases} \)
\( C_{g} = \frac{\mathrm{Calories} - 4P_{g} - 9F_{g}}{4} \)
Glossary of Variables
- W: Body weight in kilograms (kg).
- H: Height in centimeters (cm).
- A: Age in years.
- %BF: Body fat percentage.
- LBM: Lean body mass (kg).
- BMR: Basal Metabolic Rate (kcal/day).
- TDEE: Total Daily Energy Expenditure (kcal/day).
- r: Goal rate as a fraction (e.g., −0.2 = 20% deficit).
- P_g, F_g, C_g: Protein, fat, carbohydrate grams per day.
- p: Protein in g/kg (basis: body weight or lean mass).
- f%: Fat as percent of calories. f_kg: Fat in g/kg.
How It Works: A Step-by-Step Example
Inputs: Male, 30 years, 180 cm, 80 kg, 15% body fat, activity 1.55, goal −20%, protein 1.8 g/kg (total body weight), fat 25% calories.
- BMR (MSJ): 10×80 + 6.25×180 − 5×30 + 5 = 1780 kcal/day.
- TDEE: 1780 × 1.55 = 2759 kcal/day.
- Target calories: 2759 × (1 − 0.20) = 2207 kcal/day.
- Protein: 1.8 × 80 = 144 g (576 kcal).
- Fat: 25% × 2207 = 551.8 kcal → 61.3 g.
- Carbs: (2207 − 576 − 551.8) / 4 = 269.8 g.
Frequently Asked Questions (FAQ)
Do I need my body fat percentage?
No. If you don’t know it, use Mifflin–St Jeor. If you have a good estimate, Katch–McArdle can personalize BMR via lean mass.
What if my carbs calculate as negative?
Reduce protein or fat targets, or increase total calories. Very high protein plus high fat at low calories can leave no room for carbs.
How fast should I lose or gain?
Common guidance: lose 0.25–1.0% body weight per week; gain 0.25–0.5% to minimize fat gain. Adjust the goal percentage accordingly.
Are activity multipliers accurate for athletes?
They are averages. Endurance or physically demanding jobs may require higher multipliers. Use weight trends to calibrate.
Should protein be based on lean mass or total weight?
If body fat is high or known, lean-mass basis can be more appropriate. Otherwise, total body weight basis is fine.
Is fiber included?
This calculator targets total carbohydrates. Aim for 25–35 g/day of fiber from whole foods for health and satiety.
Can I export or print results?
Copy the results into your notes or a meal-planning tool. A print-friendly layout is supported by your browser.
Formula (LaTeX) + variables + units
','
= sel => Array.from(document.querySelectorAll(sel)); const clamp = (v, min, max) => Math.max(min, Math.min(max, v)); const toNumber = (v) => { const n = Number(v); return Number.isFinite(n) ? n : NaN; }; const formatKcal = n => isFinite(n) ? Math.round(n).toLocaleString() + ' kcal' : '—'; const formatGrams = n => isFinite(n) ? Math.round(n) + ' g' : '—'; const inchesFromFtIn = (ft, inch) => (ft*12 + inch); const cmFromInches = inches => inches * 2.54; const kgFromLb = lb => lb * 0.45359237; const lbFromKg = kg => kg / 0.45359237; // Elements const ageEl = $('#age'); const heightCmEl = $('#heightCm'); const heightFtEl = $('#heightFt'); const heightInEl = $('#heightIn'); const weightKgEl = $('#weightKg'); const weightLbEl = $('#weightLb'); const bodyFatEl = $('#bodyFat'); const unitsMetricEl = $('#unitsMetric'); const unitsImperialEl = $('#unitsImperial'); const heightMetricGroup = $('#heightMetricGroup'); const heightImperialGroup = $('#heightImperialGroup'); const weightMetricGroup = $('#weightMetricGroup'); const weightImperialGroup = $('#weightImperialGroup'); const eqMSJ = $('#eqMSJ'); const eqKM = $('#eqKM'); const equationNote = $('#equationNote'); const activityEl = $('#activity'); const proteinPerKgEl = $('#proteinPerKg'); const proteinBasisEl = $('#proteinBasis'); const proteinMirrorEl = $('#proteinMirror'); const fatMethodEl = $('#fatMethod'); const fatPercentEl = $('#fatPercent'); const fatPerKgEl = $('#fatPerKg'); const goalRateEl = $('#goalRate'); const goalCustomEl = $('#goalCustom'); const errors = { age: $('#ageError'), height: $('#heightError'), heightImp: $('#heightImpError'), weight: $('#weightError'), weightImp: $('#weightImpError'), bodyFat: $('#bodyFatError'), activity: $('#activityError'), goal: $('#goalError'), }; const outputs = { bmr: $('#bmrOut'), act: $('#activityOut'), tdee: $('#tdeeOut'), cal: $('#calorieOut'), protein: $('#proteinOut'), fat: $('#fatOut'), carbs: $('#carbOut') }; // Tooltips
('input[name="goal"]').forEach(r => r.addEventListener('change', () => { syncGoalUI(); compute(); })); goalRateEl.addEventListener('change', () => compute()); goalCustomEl.addEventListener('input', () => compute()); syncGoalUI(); // Fat method UI function syncFatUI(){ const method = fatMethodEl.value; if (method === 'percent') { fatPercentEl.hidden = false; fatPerKgEl.hidden = true; } else { fatPercentEl.hidden = true; fatPerKgEl.hidden = false; } } fatMethodEl.addEventListener('change', () => { syncFatUI(); compute(); }); fatPercentEl.addEventListener('input', compute); fatPerKgEl.addEventListener('input', compute); syncFatUI(); // Protein mirror to per-lb for clarity function updateProteinMirror(){ const perKg = toNumber(proteinPerKgEl.value); if (!isFinite(perKg)) { proteinMirrorEl.textContent = '—'; return; } const perLb = perKg / 2.2046226218; // g/kg to g/lb proteinMirrorEl.textContent = '≈ ' + (Math.round(perLb*100)/100).toFixed(2) + ' g/lb basis'; } proteinPerKgEl.addEventListener('input', () => { updateProteinMirror(); compute(); }); proteinBasisEl.addEventListener('change', compute); updateProteinMirror(); // Validation helpers function setError(el, msg, key){ el.setAttribute('aria-invalid', 'true'); if (key && errors[key]) errors[key].textContent = msg; } function clearError(el, key){ el.removeAttribute('aria-invalid'); if (key && errors[key]) errors[key].textContent = ''; } // Field-level validation (on blur) ageEl.addEventListener('blur', () => { const v = toNumber(ageEl.value); if (!isFinite(v) || v < 10 || v > 100) setError(ageEl, 'Please enter an age between 10 and 100.', 'age'); else clearError(ageEl, 'age'); }); heightCmEl.addEventListener('blur', () => { const v = toNumber(heightCmEl.value); if (!isFinite(v) || v < 120 || v > 230) setError(heightCmEl, 'Height must be between 120 and 230 cm.', 'height'); else clearError(heightCmEl, 'height'); }); heightFtEl.addEventListener('blur', () => { const ft = toNumber(heightFtEl.value), inch = toNumber(heightInEl.value); if (!isFinite(ft) || !isFinite(inch) || ft < 4 || ft > 7 || inch < 0 || inch > 11) setError(heightFtEl, 'Enter a valid height between 4’0” and 7’11”.', 'heightImp'); else clearError(heightFtEl, 'heightImp'); }); heightInEl.addEventListener('blur', () => { const ft = toNumber(heightFtEl.value), inch = toNumber(heightInEl.value); if (!isFinite(ft) || !isFinite(inch) || ft < 4 || ft > 7 || inch < 0 || inch > 11) setError(heightInEl, 'Enter a valid height between 4’0” and 7’11”.', 'heightImp'); else clearError(heightInEl, 'heightImp'); }); weightKgEl.addEventListener('blur', () => { const v = toNumber(weightKgEl.value); if (!isFinite(v) || v < 30 || v > 300) setError(weightKgEl, 'Weight must be between 30 and 300 kg.', 'weight'); else clearError(weightKgEl, 'weight'); }); weightLbEl.addEventListener('blur', () => { const v = toNumber(weightLbEl.value); if (!isFinite(v) || v < 66 || v > 660) setError(weightLbEl, 'Weight must be between 66 and 660 lb.', 'weightImp'); else clearError(weightLbEl, 'weightImp'); }); bodyFatEl.addEventListener('blur', () => { const v = toNumber(bodyFatEl.value); if (bodyFatEl.value === '') { clearError(bodyFatEl, 'bodyFat'); return; } if (!isFinite(v) || v < 3 || v > 60) setError(bodyFatEl, 'Enter body fat between 3% and 60%, or leave empty.', 'bodyFat'); else clearError(bodyFatEl, 'bodyFat'); }); activityEl.addEventListener('blur', () => { const v = toNumber(activityEl.value); if (!isFinite(v) || v < 1.1 || v > 2.5) setError(activityEl, 'Please select a valid activity level.', 'activity'); else clearError(activityEl, 'activity'); }); // Equation note when Katch requires BF% function checkEquationRequirement(){ if (eqKM.checked) { const bf = toNumber(bodyFatEl.value); if (!isFinite(bf)) { equationNote.textContent = 'Katch–McArdle requires a valid body fat percentage.'; } else { equationNote.textContent = ''; } } else { equationNote.textContent = ''; } } eqMSJ.addEventListener('change', () => { checkEquationRequirement(); compute(); }); eqKM.addEventListener('change', () => { checkEquationRequirement(); compute(); }); bodyFatEl.addEventListener('input', () => { checkEquationRequirement(); compute(); }); // Input events -> compute [ageEl, heightCmEl, heightFtEl, heightInEl, weightKgEl, weightLbEl, activityEl].forEach(el => { el.addEventListener('input', compute); });
('input[name="units"]').forEach(el => el.addEventListener('change', () => { applyUnitsUI(); compute(); })); function getInputs(){ const metric = unitsMetricEl.checked; const sex = (document.querySelector('input[name="sex"]:checked')||{}).value || 'male'; const age = toNumber(ageEl.value); const activity = toNumber(activityEl.value); const equation = eqKM.checked ? 'km' : 'msj'; let heightCm, weightKg; if (metric) { heightCm = toNumber(heightCmEl.value); weightKg = toNumber(weightKgEl.value); } else { const ft = toNumber(heightFtEl.value); const inch = toNumber(heightInEl.value); const inches = inchesFromFtIn(ft, inch); heightCm = cmFromInches(inches); weightKg = kgFromLb(toNumber(weightLbEl.value)); } const bf = bodyFatEl.value === '' ? NaN : toNumber(bodyFatEl.value); // Goal rate const goal = (document.querySelector('input[name="goal"]:checked') || {}).value || 'maintain'; let rate = 0; if (goal === 'custom') { const custom = toNumber(goalCustomEl.value); rate = isFinite(custom) ? clamp(custom, -40, 40) / 100 : 0; if (!isFinite(custom)) errors.goal.textContent = 'Enter a custom percentage between −40 and +40.'; else errors.goal.textContent = ''; } else { rate = toNumber(goalRateEl.value); } // Macros const pPerKg = toNumber(proteinPerKgEl.value); const pBasis = proteinBasisEl.value; // 'tbw' or 'lbm' const fatMethod = fatMethodEl.value; const fatPercent = toNumber(fatPercentEl.value); const fatPerKg = toNumber(fatPerKgEl.value); return { metric, sex, age, heightCm, weightKg, bf, activity, equation, goal, rate, pPerKg, pBasis, fatMethod, fatPercent, fatPerKg }; } function compute(){ const inp = getInputs(); // Basic validity const validAge = isFinite(inp.age) && inp.age >= 10 && inp.age <= 100; const validH = isFinite(inp.heightCm) && inp.heightCm >= 120 && inp.heightCm <= 230; const validW = isFinite(inp.weightKg) && inp.weightKg >= 30 && inp.weightKg <= 300; const validAct = isFinite(inp.activity) && inp.activity >= 1.1 && inp.activity <= 2.5; if (!validAge || !validH || !validW || !validAct) { outputs.bmr.textContent = '—'; outputs.tdee.textContent = '—'; outputs.act.textContent = '—'; outputs.cal.textContent = '—'; outputs.protein.textContent = '—'; outputs.fat.textContent = '—'; outputs.carbs.textContent = '—'; return; } // BMR let bmr = NaN; if (inp.equation === 'msj') { const s = (inp.sex === 'male') ? 5 : -161; bmr = 10*inp.weightKg + 6.25*inp.heightCm - 5*inp.age + s; } else { const bf = toNumber(inp.bf); if (isFinite(bf)) { const lbm = inp.weightKg * (1 - bf / 100); bmr = 370 + 21.6 * lbm; } else { outputs.bmr.textContent = '—'; outputs.tdee.textContent = '—'; outputs.act.textContent = '—'; outputs.cal.textContent = '—'; outputs.protein.textContent = '—'; outputs.fat.textContent = '—'; outputs.carbs.textContent = '—'; return; } } const tdee = bmr * inp.activity; const targetCalories = tdee * (1 + inp.rate); // Protein grams let kgBasis = inp.weightKg; if (inp.pBasis === 'lbm') { if (isFinite(inp.bf)) { kgBasis = inp.weightKg * (1 - inp.bf / 100); } else { // fall back to TBW if no BF% kgBasis = inp.weightKg; } } const proteinG = Math.max(0, inp.pPerKg * kgBasis); // Fat grams let fatG = 0; if (inp.fatMethod === 'percent') { const pct = clamp(isFinite(inp.fatPercent) ? inp.fatPercent : 25, 5, 80) / 100; fatG = (targetCalories * pct) / 9; } else { const perKg = clamp(isFinite(inp.fatPerKg) ? inp.fatPerKg : 0.8, 0.2, 3.0); fatG = perKg * kgBasis; } // Carbs grams const remainingKcal = targetCalories - (proteinG * 4) - (fatG * 9); const carbsG = Math.max(0, remainingKcal / 4); // Output outputs.bmr.textContent = formatKcal(bmr); outputs.act.textContent = inp.activity.toFixed(2); outputs.tdee.textContent = formatKcal(tdee); outputs.cal.textContent = formatKcal(targetCalories); outputs.protein.textContent = formatGrams(proteinG); outputs.fat.textContent = formatGrams(fatG); outputs.carbs.textContent = formatGrams(carbsG); } // Initial compute compute(); // Footer dates const y = new Date().getFullYear(); const review = new Date(); $('#year').textContent = y; $('#reviewDate').textContent = review.toLocaleDateString(undefined, { year:'numeric', month:'long', day:'numeric' }); // Keyboard accessibility for radio "cards"
BMR (Mifflin–St Jeor): For men: \( \mathrm{BMR} = 10W + 6.25H - 5A + 5 \) For women: \( \mathrm{BMR} = 10W + 6.25H - 5A - 161 \) BMR (Katch–McArdle): \( \mathrm{BMR} = 370 + 21.6 \times \mathrm{LBM} \) where \( \mathrm{LBM} = W \times (1 - \frac{\%BF}{100}) \) Total Daily Energy Expenditure (TDEE): \( \mathrm{TDEE} = \mathrm{BMR} \times \mathrm{Activity} \) Goal calories: \( \mathrm{Calories}_{target} = \mathrm{TDEE} \times (1 + r) \) where r is goal rate (e.g., −0.20) Macros: \( P_{g} = p \times \text{kg basis} \), \( F_{g} = \begin{cases} \frac{f\% \times \mathrm{Calories}}{9} & (\%) \\ f_{kg}\times \text{kg basis} & (\mathrm{g/kg})\end{cases} \) \( C_{g} = \frac{\mathrm{Calories} - 4P_{g} - 9F_{g}}{4} \)
- No variables provided in audit spec.
- Health and Fitness — calcdomain.com · Accessed 2026-01-19
https://calcdomain.com/health-fitness - DOI — doi.org · Accessed 2026-01-19
https://doi.org/10.1093/ajcn/51.2.241 - DOI — doi.org · Accessed 2026-01-19
https://doi.org/10.1136/bjsports-2017-097608
Last code update: 2026-01-19
- Initial audit spec draft generated from HTML extraction (review required).
- Verify formulas match the calculator engine and convert any text-only formulas to LaTeX.
- Confirm sources are authoritative and relevant to the calculator methodology.