-5

Have a problem:

string bmi(double w, double h)
{
    string answer;
    double bmi = w / (h*h);
    cout << setprecision(9) << bmi << endl;
    if (bmi <= 18.5) {
        answer = "Underweight";
    } else if (bmi <= 25.0){
        answer = "Normal";
    } else if (bmi <= 30.0){
        answer = "Overweight";
    } else {
        answer = "Obese";
    }
    return answer;
}

int main() {
    cout << bmi(81.585, 2.1) << endl;
    cout << bmi(90.25, 1.9) << endl;
    cout << bmi(86.7, 1.7) << endl;
    cout << bmi(200, 1.6) << endl;
    return 0;
}

3 call must give "Overweight" answer, but instead throw "Obese", what i doing wrong?

Engylizium
  • 21
  • 4
  • Paste your code here please – frslm Oct 07 '17 at 19:27
  • Not working images =(] – Engylizium Oct 07 '17 at 19:28
  • Test against `30.00001` instead of `30.0`. – rustyx Oct 07 '17 at 19:30
  • You have been a member for almost a year. That's plenty of time to have read [the help pages](http://stackoverflow.com/help), especially the sections named ["What topics can I ask about here?"](http://stackoverflow.com/help/on-topic) and ["What types of questions should I avoid asking?"](http://stackoverflow.com/help/dont-ask). Also please [take the tour](http://stackoverflow.com/tour) and [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask). Lastly please learn how to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – Some programmer dude Oct 07 '17 at 19:31
  • Also note that `30` is an *integer* value (of type `int`) but you are using type `double` which have problems with rounding on binary platforms using common formats. Please take some time to read [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Some programmer dude Oct 07 '17 at 19:32

1 Answers1

1

This is just the nature of finite precision representations. I'll show you an example in decimal:

Say you represent 1/3 as "0.333333". If you compute (1/3 + 1/3 + 1/3) you will get "0.999999" instead of "1.0". So if you check if it's greater than or equal to one, you will get false.

Just as 1/3 has no exact decimal representation, 1/10 has no exact binary representation. So don't use finite precision numbers in applications where exact answers are required.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Yeah, i have that in mind when thought about problem. But why previous code works and how i can write it right? – Engylizium Oct 07 '17 at 19:30
  • @Engylizium I don't know what you mean by "previous code works". Maybe by luck or maybe it just happened to not trigger this problem. As for how to write it right, perhaps you could use `<= 30.00001`. – David Schwartz Oct 07 '17 at 19:32
  • 1
    Fundamentally, you have to decide what you want to do when the answer is so close to 30 that there is no reliable way to tell for sure on which side of 30 it falls. Otherwise, use exact representations all the way through. – David Schwartz Oct 07 '17 at 19:33
  • I mean with 25.0 and 18.5 it works. Thanks, i would keep in mind that. im just newbie in c++. Before worked with Swift – Engylizium Oct 07 '17 at 19:36
  • Right. Sometimes it will happen to give the answer you want and sometimes it will happen to give the answer you don't want. That's the nature of using a method that is unreliable. If you checked if (1/3 + 1/3 + 1/3) was less than or equal to 1, you'd get the right answer. – David Schwartz Oct 07 '17 at 19:37
  • Although it was printed as 30, it was represented as 30.000000000000004. That's why (bmi <= 30.0) was false. – DML Oct 08 '17 at 11:03