Issue
I am making a BMI app. I have this code:
enum MathHelper {
static func computeBMI(kg: Decimal, cm: Decimal) -> Decimal {
return kg / cm / cm * 10_000
}
static func computeWeight(cm: Decimal, bmi: Decimal) -> Decimal {
return bmi * cm * cm / 10_000
}
static func computeWeightRange(
cm: Decimal,
bmiRange: (from: Decimal, to: Decimal))
-> (from: Decimal, to: Decimal)
{
let fromWeight = computeWeight(cm: cm, bmi: bmiRange.from)
let toWeight = computeWeight(cm: cm, bmi: bmiRange.to)
return (from: fromWeight, to: toWeight)
}
}
Now I print the from/to pair, with 1 fraction length.
print(Decimal.FormatStyle.number.precision(.fractionLength(1)).format(from))
print(Decimal.FormatStyle.number.precision(.fractionLength(1)).format(to))
When I run this code with height 180 cm, BMI range from 18.5 to 24.9 (which is the BMI range for healthy weight), I got 59.9 – 80.7 weight range.
But this is not correct. The weight range should be 59.7-80.8. Because if I put in 59.7 and 80.8 into the computeBMI
function and print result in 1 fraction length, it’s still within range 18.5-24.9.
Feel free to try it out. This is minimal reproducible code:
enum MathHelper {
static func computeBMI(kg: Decimal, cm: Decimal) -> Decimal {
return kg / cm / cm * 10_000
}
static func computeWeight(cm: Decimal, bmi: Decimal) -> Decimal {
return bmi * cm * cm / 10_000
}
static func computeWeightRange(
cm: Decimal,
bmiRange: (from: Decimal, to: Decimal))
-> (from: Decimal, to: Decimal)
{
let fromWeight = computeWeight(cm: cm, bmi: bmiRange.from)
let toWeight = computeWeight(cm: cm, bmi: bmiRange.to)
return (from: fromWeight, to: toWeight)
}
}
func format(_ decimal: Decimal) -> String {
return Decimal.FormatStyle.number.precision(.fractionLength(1)).format(decimal)
}
let height: Decimal = 180
let upperBMI: Decimal = 24.9
let computedUpperWeight = format(MathHelper.computeWeight(cm: height, bmi: upperBMI))
// this prints out 80.7, which is incorrect, because 80.8 is the correct answer (see below)
print("computed upper weight: \(computedUpperWeight)")
let correctUpperWeight: Decimal = 80.8
let bmiFromCorrectUpperWeight = format(MathHelper.computeBMI(kg: correctUpperWeight, cm: height))
// This prints out 24.9, which is still within the uppoer bound
print("BMI from correct upper weight \(bmiFromCorrectUpperWeight)")
Solution
While flanker’s argument is valid, BMI values are typically represented with 1 precision in real world application.
My recommendation is to adjust your BMI chart range by 0.05.
For example, with these 2 ranges (i quote from wikipedia).
- Normal: 18.5-24.9
- Overweight 25-29.9
You can represent your range in your code like this:
- Normal: 18.45-24.95
- Overweight 24.95-29.95
This should solve your problem.
Answered By – OMGPOP
Answer Checked By – Jay B. (BugsFixing Admin)