On this page
Python
CATEGORIES = [(18.5, "Underweight"), (25, "Healthy weight"), (30, "Overweight"),
(35, "Obesity class 1"), (40, "Obesity class 2"), (float("inf"), "Obesity class 3")]
def bmi_metric(weight_kg: float, height_cm: float) -> float:
return weight_kg / (height_cm / 100) ** 2
def bmi_imperial(weight_lb: float, height_in: float) -> float:
return 703 * weight_lb / height_in ** 2
def category(bmi: float) -> str:
rounded = round(bmi, 1)
return next(name for limit, name in CATEGORIES if rounded < limit)
bmi = bmi_metric(65, 170)
print(round(bmi, 1), category(bmi)) # 22.5 Healthy weight
JavaScript
const CATEGORIES = [[18.5, 'Underweight'], [25, 'Healthy weight'], [30, 'Overweight'],
[35, 'Obesity class 1'], [40, 'Obesity class 2'], [Infinity, 'Obesity class 3']];
const bmiMetric = (kg, cm) => kg / (cm / 100) ** 2;
const bmiImperial = (lb, inches) => (703 * lb) / inches ** 2;
const round1 = n => Math.round(n * 10) / 10;
const category = bmi => CATEGORIES.find(([limit]) => round1(bmi) < limit)[1];
const bmi = bmiImperial(150, 67);
console.log(round1(bmi), category(bmi)); // 23.5 'Healthy weight'
PHP
function bmi_metric(float $kg, float $cm): float
{
return $kg / (($cm / 100) ** 2);
}
function bmi_category(float $bmi): string
{
$b = round($bmi, 1);
return match (true) {
$b < 18.5 => 'Underweight',
$b < 25 => 'Healthy weight',
$b < 30 => 'Overweight',
default => 'Obesity',
};
}
echo round(bmi_metric(65, 170), 1); // 22.5
SQL
SELECT
person_id,
ROUND(weight_kg / POWER(height_cm / 100.0, 2), 1) AS bmi,
CASE
WHEN ROUND(weight_kg / POWER(height_cm / 100.0, 2), 1) < 18.5 THEN 'Underweight'
WHEN ROUND(weight_kg / POWER(height_cm / 100.0, 2), 1) < 25 THEN 'Healthy weight'
WHEN ROUND(weight_kg / POWER(height_cm / 100.0, 2), 1) < 30 THEN 'Overweight'
ELSE 'Obesity'
END AS category
FROM measurements
WHERE height_cm > 0;
Use 100.0, not 100, so databases that do integer division don't truncate the height.
Test cases for your own code
These are worked out by hand on this site and make good unit tests:
| Input | Expected BMI | Category |
|---|---|---|
| 65 kg, 170 cm | 22.5 | Healthy weight |
| 60 kg, 165 cm | 22.0 | Healthy weight |
| 150 lb, 67 in | 23.5 | Healthy weight |
| 190 lb, 70 in | 27.3 | Overweight |
| BMI 24.96 | 25.0 | Overweight (after rounding) |
Things to watch for
- Categorizing the unrounded value. 24.96 displays as 25.0 but would be "healthy" if you test the raw number. Round first.
- Integer division. In some languages and databases, 170 / 100 is 1. Use decimals.
- Children. Under 20, BMI needs an age- and sex-specific percentile, not these categories. How BMI percentiles are calculated.
Frequently asked questions
Which formula should my app use for pounds?
703 * lb / in² is the CDC's formula. Converting to kilograms first gives the same result to one decimal place.
Should I store BMI or calculate it?
Store height and weight, and calculate BMI when you need it. That way corrections to either measurement update the BMI automatically.
Sources
This page is for education and is not medical advice. Talk with a healthcare professional about your weight and health.
