2

Here is part of my code:

students = 0
weight = 0
height = 0

while students < 5:
    name = input("Please enter the name. ")
    students = students + 1

while weight == 0:
    try:
        weight = float(input("Please enter the weight in kgs "))

        if weight <= 0:
            print ("Please enter a number greater than zero ")
            weight = 0
            continue

    except ValueError:
        print ("No number found, please enter a number greater than zero ")
        weight = 0
        continue

while height == 0:
    try:
        height = float(input("Please enter the height in metres "))


        if height <= 0:
            print ("Please enter a number greater than zero ")
            height = 0
            continue

    except ValueError:
        print ("No number found, please enter a number greater than zero ")
        height = 0
        continue

BMI = (weight/(height*height))
print (name, "has the BMI of", "%.2f" %BMI)
if BMI < 18.5:
    print ("The student is underweight.")
elif 18.5 <= BMI <= 27:
    print ("The student is a healthy weight.")
elif BMI > 27:
    print ("The student is overweight.")

weight = 0
height = 0

However, when the BMI is 18.5 it says that the student is underweight and when the BMI is 27 it says the student is overweight, when both should actually be a healthy weight? e.g. 53.456 for weight and 1.7m for height shows up as underweight

  • 1
    Post ALL the relevant parts of your code (where are the values for `weight` and `height`? – inspectorG4dget Aug 28 '14 at 02:45
  • 1
    possible duplicate of [Python rounding error with float numbers](http://stackoverflow.com/questions/5997027/python-rounding-error-with-float-numbers) – timrau Aug 28 '14 at 02:47
  • 1
    ...and you're certain that `BMI` is *exactly* 18.5? Not the rounded-up value that you might see by truncating its presentation to two decimal places? – Makoto Aug 28 '14 at 02:49
  • updated, I just want to know whether there is a simple solution for this? The link you posted looks...not simple ._. – Valkyrie Yan Aug 28 '14 at 02:50
  • Makoto, I tried it by 1.7*1.7*18.5 on a calculator to check my code, so it should be right. – Valkyrie Yan Aug 28 '14 at 02:51
  • You sure that's the calculation you used? That's a *much* higher number than one would expect. – Makoto Aug 28 '14 at 02:53

3 Answers3

2
>>> 53.456/(1.7*1.7)
18.496885813148793
>>> 53.456/(1.7*1.7) <= 18
False

Seems to me like its just floating point errors, try

>>> round(53.456/(1.7*1.7), 2)
18.5
>>> round(53.456/(1.7*1.7), 2) <= 18.5
True

Problem solving strategy for the future: whenever something doesn't quite seem right, crack open the python shell and mess around a bit, you might find the solution yourself.

user2085282
  • 1,077
  • 1
  • 8
  • 16
  • [Rounding](https://docs.python.org/3.5/library/functions.html#round) is not guaranteed to allow equality testing of floating point numbers. – Andrew Johnson Aug 28 '14 at 03:18
  • Which might be a problem if equality was the only condition being tested for, in which case a tolerance would be in order. But its not, and in this case, the number would have been rounded anyways by whatever human doing this paperwork. – user2085282 Aug 28 '14 at 03:22
  • The op is testing boundary cases and is asking why `BMI = 18.5` matches the condition `BMI < 18.5`. So yes, this is a question of exact equality. – Andrew Johnson Aug 28 '14 at 03:27
  • @AndrewJohnson: It would be very surprising indeed (and worthy of a bug report) if `BMI = 18.5; BMI < 18.5` gave a result of `True` in Python. It seems much more likely that the OP is testing a value that *isn't* exactly equal to `18.5`. – Mark Dickinson Aug 28 '14 at 10:52
0

Generally speaking, floating-point numbers are not exact due to the nature of how they are represented in the computer. They are just really close approximations. Therefore, testing for exact equality with a floating point number is bound to lead to frustration. You should probably either round your numbers off or not test for equality.

The link posted by timrau is actually a pretty good introduction to the topic if you're interested in exploring it further.

0

Floating point numbers only approximate decimal numbers. Your comparison could go over/under depending on what order you multiply or divide or the time of day... not quite. If you want meaningful equality comparisons then take a look at the decimal library in python. You can set the precision to two decimal places and suddenly your comparisons and calculator math should work.

Andrew Johnson
  • 3,078
  • 1
  • 18
  • 24
  • "If you want meaningful equality comparisons..." Not really: both `decimal.Decimal` and `float` are floating-point types, and equality comparisons are exactly as meaningful in one type as in the other. – Mark Dickinson Aug 28 '14 at 13:44
  • From the [decimal](https://docs.python.org/2/library/decimal.html#module-decimal) docs "Decimal numbers can be represented exactly. In contrast, numbers like 1.1 and 2.2 do not have exact representations in binary floating point." – Andrew Johnson Aug 28 '14 at 14:24
  • Well yes, of course: numbers that can be exactly expressed in decimal can be exactly represented by `Decimal`. Similarly, numbers that can be exactly expressed in binary (and don't have more than 53 bits of precision, etc.) can be exactly represented by `float`. This has nothing to do with 'meaningful equality'. – Mark Dickinson Aug 28 '14 at 15:21