healthfitness

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2026 License: MIT Imports: 4 Imported by: 0

README

health-fitness-formulas-go

Go Reference Go Report Card

Published health and fitness formulas, implemented exactly as they appear in the source papers and guidance. Zero dependencies, metric-first, no rounding inside the functions — callers round for display.

This is a Go port of health-fitness-formulas (npm). The test suite is a direct translation of the JavaScript one — same cases, same expected values, same tolerances — so the two implementations are held to a single standard rather than drifting apart.

go get github.com/javeed450-sudo/health-fitness-formulas-go

Usage

package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	bmi, err := hf.BMI(70, 170) // kg, cm
	if err != nil {
		panic(err)
	}
	fmt.Printf("BMI %.1f\n", bmi) // BMI 24.2

	// BMR is rounded to a whole kcal before the activity multiplier is applied.
	t, _ := hf.TDEENamed(hf.Male, 80, 180, 30, "moderate")
	fmt.Println(t.BMR, t.TDEE) // 1780 2759

	p, _ := hf.Pace(10, 50*60)
	s, _ := hf.FormatDuration(p.SecondsPerKm)
	fmt.Println(s) // 5:00
}

What's included

Area Functions
Body composition BMI · BodyFatNavy · LeanBodyMassFromBodyFat · LeanBodyMassBoer · FFMI · WaistToHeightRatio · BodySurfaceArea
Energy BMRMifflinStJeor · BMRKatchMcArdle · TDEE · TDEENamed · ActivityLevels
Training OneRepMax · MaxHeartRate · TargetHeartRate · Pace · FormatDuration

Sources

Each function cites its own source in its doc comment. The principal ones:

Formula Source
BMI Quetelet's index; named BMI by Keys et al., Journal of Chronic Diseases (1972)
Body fat (circumference) Hodgdon & Beckett, Naval Health Research Center Report 84-11 (1984)
Lean body mass Boer P., American Journal of Physiology (1984)
FFMI normalisation Kouri et al., Clinical Journal of Sport Medicine (1995)
BMR Mifflin MD, St Jeor ST et al., American Journal of Clinical Nutrition (1990)
Body surface area Mosteller (1987), DuBois (1916), Haycock (1978), Gehan & George (1970)
One-rep max Epley (1985); Brzycki (1993)
Max heart rate Tanaka, Monahan & Seals, JACC (2001)
Target heart rate Karvonen heart-rate reserve method

Two behaviours worth knowing

TDEE rounding order is part of the definition. BMR is rounded to a whole kcal before the activity multiplier is applied. Multiplying the unrounded value instead diverges by up to ~2 kcal, and more at high multipliers. The order is pinned, not incidental.

The Navy body fat equation is named for its origin, not its current status. The U.S. Department of Defense moved every service to a waist-to-height ratio screen on 1 January 2026, and the Army implemented it on 7 July 2026, retiring the tape test. The formula remains a sound field estimate; it is no longer a service standard. Use WaistToHeightRatio for the current one.

Not medical advice

These are population-level estimates for education. They are not diagnostic and not a substitute for clinical judgement. Each function documents the limits of its method.

Interactive versions

The calculators these formulas power are at healthycalculatorhub.com.

License

MIT © Javeed Shaik

Documentation

Overview

Package healthfitness implements published health and fitness formulas exactly as they appear in the source papers and guidance.

Zero dependencies, metric-first, and no rounding is applied inside the functions — callers round for display. The one deliberate exception is TDEE, where the rounding order is part of the definition; see that function.

Every function is a straight transcription of the equation cited in its own doc comment. The test suite asserts parity with the JavaScript implementation published as health-fitness-formulas on npm, using the same cases, values and tolerances, so the two ports are held to one standard rather than drifting into two.

The interactive versions of these calculations are published at https://healthycalculatorhub.com

Not medical advice

These are population-level estimates for education. They are not diagnostic and not a substitute for clinical judgement. Each function documents the limits of its method.

Index

Examples

Constants

View Source
const KmPerMile = 1.609344

KmPerMile is the exact international mile in kilometres.

Variables

View Source
var ActivityLevels = map[string]float64{
	"sedentary":  1.2,
	"light":      1.375,
	"moderate":   1.55,
	"active":     1.725,
	"veryActive": 1.9,
}

ActivityLevels maps the named activity levels to the multipliers applied to BMR to reach TDEE.

Functions

func BMI

func BMI(kg, cm float64) (float64, error)

BMI returns the Body Mass Index: weight in kilograms divided by height in metres squared. Height is given in centimetres.

Quetelet's index; adopted as "BMI" by Keys et al., Journal of Chronic Diseases (1972). WHO adult cut-offs: below 18.5 underweight, 18.5–24.9 healthy, 25–29.9 overweight, 30 and above obesity.

BMI does not distinguish muscle from fat and says nothing about fat distribution. For the interactive version with the WHO bands shown, see https://healthycalculatorhub.com/bmi-calculator

Example
package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	bmi, err := hf.BMI(70, 170) // kg, cm
	if err != nil {
		panic(err)
	}
	fmt.Printf("%.1f\n", bmi)
}
Output:
24.2

func BMRKatchMcArdle

func BMRKatchMcArdle(leanBodyMassKg float64) (float64, error)

BMRKatchMcArdle returns basal metabolic rate in kcal/day from lean body mass rather than total weight: 370 + 21.6 * lean mass.

Preferable to BMRMifflinStJeor when body fat percentage is known and reliable, since it does not need to infer composition from height and weight.

func BMRMifflinStJeor

func BMRMifflinStJeor(sex Sex, kg, cm, age float64) (float64, error)

BMRMifflinStJeor returns basal metabolic rate in kcal/day, unrounded.

Mifflin MD, St Jeor ST, et al., American Journal of Clinical Nutrition (1990). This is the equation most widely recommended for healthy adults; it supersedes Harris-Benedict for general use.

age is in years and must be between 0 and 120.

Applied against activity multipliers at https://healthycalculatorhub.com/tdee-calculator

func BodyFatNavy

func BodyFatNavy(in NavyInput) (float64, error)

BodyFatNavy estimates body fat percentage using the U.S. Navy circumference method.

Hodgdon & Beckett, Naval Health Research Center Report 84-11 (1984), metric form.

Current military status: this equation is named for its origin, not its present standing. The U.S. Department of Defense moved every service to a waist-to-height ratio screen on 1 January 2026, and the Army implemented it on 7 July 2026, retiring the tape test. The formula remains a sound field estimate; it is no longer a service standard. Use WaistToHeightRatio for the current standard.

The interactive version is at https://healthycalculatorhub.com/body-fat-calculator

Example

The male equation needs neck, waist and height; the female one additionally needs hip.

package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	pct, err := hf.BodyFatNavy(hf.NavyInput{
		Sex: hf.Male, NeckCm: 38, WaistCm: 85, HeightCm: 175,
	})
	if err != nil {
		panic(err)
	}
	fmt.Printf("%.1f%%\n", pct)
}
Output:
16.9%

func BodySurfaceArea

func BodySurfaceArea(kg, cm float64, formula BSAFormula) (float64, error)

BodySurfaceArea returns body surface area in square metres. An empty formula defaults to Mosteller. All four agree within about 5% at adult sizes.

All four are shown side by side at https://healthycalculatorhub.com/bsa-calculator

func FormatDuration

func FormatDuration(seconds float64) (string, error)

FormatDuration renders a number of seconds as m:ss, or h:mm:ss once past an hour. Seconds are rounded to the nearest whole second.

func LeanBodyMassBoer

func LeanBodyMassBoer(sex Sex, kg, cm float64) (float64, error)

LeanBodyMassBoer returns lean body mass in kilograms using the Boer equation.

Boer P., American Journal of Physiology (1984).

The result is clamped to the range [0, kg]: the equation is a population fit and can exceed body weight at extreme height-to-weight combinations.

func LeanBodyMassFromBodyFat

func LeanBodyMassFromBodyFat(kg, bodyFatPct float64) (float64, error)

LeanBodyMassFromBodyFat returns lean body mass in kilograms given weight and a known body fat percentage. bodyFatPct must be between 3 and 60.

See https://healthycalculatorhub.com/lean-body-mass-calculator

func MaxHeartRate

func MaxHeartRate(age float64, formula HRFormula) (float64, error)

MaxHeartRate returns estimated maximum heart rate in beats per minute, unrounded. An empty formula defaults to Tanaka. age must be between 0 and 120.

func WaistToHeightRatio

func WaistToHeightRatio(waist, height float64) (float64, error)

WaistToHeightRatio returns waist divided by height. The result is dimensionless, so the two measurements need only share a unit.

Two separate sets of thresholds apply, and they are not interchangeable:

  • Public health (UK NICE NG246): below 0.5 is the "keep your waist to less than half your height" rule; 0.5–0.59 increased; 0.6 and above high central adiposity.
  • U.S. military (from 1 January 2026): below 0.55 for Army, Navy, Air Force and Space Force; below 0.52 for the Marine Corps. The limits are strict inequalities — exactly 0.55 does not pass.

See https://healthycalculatorhub.com/waist-to-height-ratio-calculator

Types

type BSAFormula

type BSAFormula string

BSAFormula selects the body surface area equation used by BodySurfaceArea.

const (
	// Mosteller is the default: sqrt(height * weight / 3600). Mosteller RD,
	// New England Journal of Medicine (1987).
	Mosteller BSAFormula = "mosteller"
	// DuBois is the 1916 equation, still common in oncology dosing.
	DuBois BSAFormula = "dubois"
	// Haycock is fitted across infants through adults. Haycock GB et al., Journal of
	// Pediatrics (1978).
	Haycock BSAFormula = "haycock"
	// Gehan is Gehan EA & George SL, Cancer Chemotherapy Reports (1970).
	Gehan BSAFormula = "gehan"
)

type FFMIResult

type FFMIResult struct {
	FFMI          float64
	Normalised    float64
	FatFreeMassKg float64
}

FFMIResult carries the raw index, the height-normalised value and the fat-free mass it was derived from.

func FFMI

func FFMI(kg, cm, bodyFatPct float64) (FFMIResult, error)

FFMI returns the Fat-Free Mass Index: fat-free mass divided by height in metres squared.

Normalised adjusts to a 1.8 m reference using the conventional 6.1 coefficient, as in Kouri et al., Clinical Journal of Sport Medicine (1995), so that tall and short lifters can be compared. The adjustment is a no-op at exactly 1.8 m.

bodyFatPct must be between 3 and 60. The interactive version is at https://healthycalculatorhub.com/ffmi-calculator

Example

Normalised adjusts to a 1.8 m reference so lifters of different heights compare.

package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	r, err := hf.FFMI(82, 180, 15)
	if err != nil {
		panic(err)
	}
	fmt.Printf("FFMI %.1f, normalised %.1f, fat-free %.1f kg\n",
		r.FFMI, r.Normalised, r.FatFreeMassKg)
}
Output:
FFMI 21.5, normalised 21.5, fat-free 69.7 kg

type HRFormula

type HRFormula string

HRFormula selects the maximum heart rate equation.

const (
	// Tanaka is 208 - 0.7 * age. Tanaka, Monahan & Seals, Journal of the American
	// College of Cardiology (2001). Better supported across adult ages, and the default.
	Tanaka HRFormula = "tanaka"
	// Classic is 220 - age. Widely used, and widely criticised for its error margin.
	Classic HRFormula = "classic"
)

type HRMethod

type HRMethod string

HRMethod reports which method TargetHeartRate used.

const (
	// Karvonen is the heart-rate reserve method, used when a usable resting heart rate
	// is supplied.
	Karvonen HRMethod = "karvonen"
	// Percentage is a plain percentage of maximum heart rate.
	Percentage HRMethod = "percentage"
)
type NavyInput struct {
	Sex      Sex
	NeckCm   float64
	WaistCm  float64
	HeightCm float64
	HipCm    float64
}

NavyInput holds the circumference measurements for BodyFatNavy. HipCm is required for the female equation and ignored for the male one.

type OneRepMaxResult

type OneRepMaxResult struct {
	Epley   float64
	Brzycki float64
	Average float64
}

OneRepMaxResult carries both estimates and their mean.

func OneRepMax

func OneRepMax(weight float64, reps int) (OneRepMaxResult, error)

OneRepMax estimates a one-rep max from a submaximal set, in whatever unit the weight was given.

Both are empirical fits and they diverge as reps rise, which is why the average is the more defensible single number:

Epley (1985):   1RM = w * (1 + reps/30)
Brzycki (1993): 1RM = w * 36 / (37 - reps)

Beyond about 10 reps neither is dependable, and beyond 20 they are not usable — reps above 20 are rejected rather than returned as a misleading number.

Both are shown side by side at https://healthycalculatorhub.com/one-rep-max-calculator

Example
package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	r, err := hf.OneRepMax(100, 5)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Epley %.1f, Brzycki %.1f, average %.1f\n", r.Epley, r.Brzycki, r.Average)
}
Output:
Epley 116.7, Brzycki 112.5, average 114.6

type PaceResult

type PaceResult struct {
	SecondsPerKm   float64
	SecondsPerMile float64
	KmPerHour      float64
	MilesPerHour   float64
}

PaceResult carries pace and average speed in both metric and imperial units.

func Pace

func Pace(km, seconds float64) (PaceResult, error)

Pace returns running pace and average speed from a distance in kilometres and a finish time in seconds.

Use FormatDuration to render SecondsPerKm or SecondsPerMile as m:ss. Splits and race predictions are at https://healthycalculatorhub.com/pace-calculator

Example
package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	p, err := hf.Pace(10, 50*60) // 10 km in 50 minutes
	if err != nil {
		panic(err)
	}
	perKm, _ := hf.FormatDuration(p.SecondsPerKm)
	perMile, _ := hf.FormatDuration(p.SecondsPerMile)
	fmt.Printf("%s /km, %s /mi, %.1f km/h\n", perKm, perMile, p.KmPerHour)
}
Output:
5:00 /km, 8:03 /mi, 12.0 km/h

type Sex

type Sex int

Sex selects the sex-specific form of an equation.

const (
	// Male selects the male form of a sex-specific equation.
	Male Sex = iota
	// Female selects the female form of a sex-specific equation.
	Female
)

func ParseSex

func ParseSex(s string) (Sex, error)

ParseSex accepts "male", "m", "female" or "f" in any case, mirroring the JavaScript port's string input. Prefer the Male and Female constants in Go code.

func (Sex) String

func (s Sex) String() string

String implements fmt.Stringer.

type TDEEResult

type TDEEResult struct {
	BMR        int
	TDEE       int
	Multiplier float64
}

TDEEResult carries the rounded BMR, the resulting TDEE and the multiplier used.

func TDEE

func TDEE(sex Sex, kg, cm, age, multiplier float64) (TDEEResult, error)

TDEE returns total daily energy expenditure: BMR multiplied by an activity factor.

Rounding order is part of the definition

BMR is rounded to a whole kcal *before* the multiplier is applied. This matches how the figure is produced on healthycalculatorhub.com. Multiplying the unrounded BMR instead diverges by enough to matter — up to about 2 kcal, and more at high multipliers — so the order is pinned here rather than left as an implementation detail.

multiplier takes a raw value; use ActivityLevels for the named levels. The interactive version is at https://healthycalculatorhub.com/tdee-calculator

func TDEENamed

func TDEENamed(sex Sex, kg, cm, age float64, activity string) (TDEEResult, error)

TDEENamed is TDEE with a named activity level: sedentary, light, moderate, active or veryActive.

Example

TDEE rounds BMR to a whole kcal before applying the activity multiplier.

package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	r, err := hf.TDEENamed(hf.Male, 80, 180, 30, "moderate")
	if err != nil {
		panic(err)
	}
	fmt.Println(r.BMR, r.TDEE, r.Multiplier)
}
Output:
1780 2759 1.55

type TargetHeartRateResult

type TargetHeartRateResult struct {
	BPM    int
	HRMax  int
	Method HRMethod
}

TargetHeartRateResult carries the target, the maximum it was derived from, and the method actually used.

func TargetHeartRate

func TargetHeartRate(age, intensity, restingHr float64, formula HRFormula) (TargetHeartRateResult, error)

TargetHeartRate returns the target heart rate for a training intensity.

With a usable resting heart rate this applies Karvonen (heart-rate reserve), which is the more individualised method:

target = (HRmax - HRrest) * intensity + HRrest

Without one — or when restingHr is implausible, meaning not between 0 and HRmax — it falls back to a plain percentage of HRmax and reports Percentage in Method, rather than silently misreporting a Karvonen figure. Pass 0 for restingHr to force the percentage method.

intensity is a fraction in (0, 1], e.g. 0.7 for 70%. An empty formula defaults to Tanaka. Zones are laid out at https://healthycalculatorhub.com/target-heart-rate-calculator

Example

With a resting heart rate this uses Karvonen; without one it falls back to a plain percentage of maximum and says so.

package main

import (
	"fmt"

	hf "github.com/javeed450-sudo/health-fitness-formulas-go"
)

func main() {
	k, _ := hf.TargetHeartRate(35, 0.7, 60, hf.Tanaka)
	p, _ := hf.TargetHeartRate(35, 0.7, 0, hf.Tanaka)
	fmt.Printf("%d bpm (%s), %d bpm (%s)\n", k.BPM, k.Method, p.BPM, p.Method)
}
Output:
147 bpm (karvonen), 129 bpm (percentage)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL