0

Code I have written gives me an error: it won't take floats as part of the range.

grade = float(input('How much was your annual average ?') )

if grade in range (65,100) :
     print ('Congratulations, you are promoted to the 2nd Secondary !')

elif grade in range ( 60, 64):
    print('You are promoted on the condition you pass a make-up exam.')

elif grade >100:
    print( 'Error, recheck value') 

else :
    print ('You have failed the academic year')
Prune
  • 76,765
  • 14
  • 60
  • 81
Aaron S.
  • 11
  • 2
  • Why use `float()` and not `int()`? – AChampion Sep 01 '17 at 22:11
  • 1
    `in range` is a bad way to test whether a number is between two other numbers. – user2357112 Sep 01 '17 at 22:11
  • @user2357112 It's not very elegant but why is it bad? `range()` object implements `__contains__()` for an efficient implementation of `in`. Not sure why this is erroring for the OP `4.5 in range(10) == False` - wrong but not an error. – AChampion Sep 01 '17 at 22:13
  • @AChampion But doesn't range have a `step`? It won't check correctly all the time. For example: `range(1, 3)` won't match `1.2343`. – Andrew Li Sep 01 '17 at 22:14
  • `range()` isn't "bad", the OP's code will create the unneeded `rage object` instead of simple comparison – RomanPerekhrest Sep 01 '17 at 22:15
  • 2
    @RomanPerekhrest `range` does not create a generator object. Creates a list in Python 2, and a `range` object in Python 3. – Moses Koledoye Sep 01 '17 at 22:15
  • @AndrewLi agreed using it for a `float()` would not be useful. – AChampion Sep 01 '17 at 22:15
  • 1
    @AChampion: Because a `range` is a sequence of integers, not an interval. It's a bad habit that fails with non-integers and causes performance regression on Python 2 or for non-integers. – user2357112 Sep 01 '17 at 22:17
  • Agreed more of a `set()` test than range test. OP is using Py3. – AChampion Sep 01 '17 at 22:18
  • moreover, if the code will be enclosed in `while` loop – RomanPerekhrest Sep 01 '17 at 22:18
  • @user2357112 it's such a popular anti-pattern that they made it work properly in Python 3, so it's no worse than the alternatives. A `range` object can quickly and easily check to see if an integer is contained within the range. It's possible that in a future version of Python they could extend it to work with other numeric types. – Mark Ransom Sep 01 '17 at 22:33
  • @MarkRansom: There's no semantic change, so it's still almost always the wrong thing for floats and misleading even for the use cases where it's safe. Something like `49.5 in range(0, 100)` will still give False, slowly, and something like `50.0 in range(0, 100)` will (still) give True, slowly. Also, even for ints, it's still slower than a chained comparison. – user2357112 Sep 01 '17 at 22:57
  • @user2357112 you're right that it's problematic for floats, `49.5 in range(0, 100)` needs to return `False` and that would confuse a lot of people. So maybe it's for the best that floats don't work. As for being slower, I think that range objects do a chained comparison in their implementation of `__contains__` so it's not that much worse. – Mark Ransom Sep 01 '17 at 23:08

3 Answers3

0

You don't need range here, you can use chained comparisons to check if the float is within the desired range:

if 65 <= grade < 100: # or <= 100
     print ('Congratulations, you are promoted to the 2nd Secondary !')   
elif 60 <= grade < 64: # or <= 64
     print('You are promoted on the condition you pass a make-up exam.')
...
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
0

range is a generated sequence of integers; it's not an interval description. For instance, your "D" range is a list of four integers:

>>> range(60, 64)
[60, 61, 62, 63]

I think that the expression you want is more like

if 60.5 < grade < 64.5:

You may want to parameterize this.

Prune
  • 76,765
  • 14
  • 60
  • 81
-1
def annual(n):
    if n in range(65,101):
        print("Congratulations, you are promoted to the 2nd Secondary !")
    if n in range(60,65):
        print("You are promoted on the condition you pass a make-up exam")
    if n>100:
        print("Error, recheck value")
    if n in range(0,60):
        print("You have failed")

How's This?

def annual(n):
if 65<=n<=100:
    print("Congratulations, you are promoted to the 2nd Secondary !")
if 60<=n<=64:
    print("You are promoted on the condition you pass a make-up exam")
if n>100:
    print("Error, recheck value")
if 0<=n<=60:
    print("You have failed")
Xenon
  • 35
  • 9
  • What would happen if they got `68.283`? Using `range` to check for an integer in between two numbers is bad. – Andrew Li Sep 01 '17 at 22:19
  • This works fine for integer values, there was nothing to say it was non integer test values – Xenon Sep 01 '17 at 22:22
  • Sure, but even if we don't factor in floats it just doesn't make sense to use `range` when using compound relational comparisons is exactly what this is for. – Andrew Li Sep 01 '17 at 22:24
  • It works fine, but still doesn't issue the problem at hand. I just want to input say 63.5 and make it state "You are promoted on the condition you pass a make-up exam" – Aaron S. Sep 01 '17 at 22:25
  • Done @AaronS. !! – Xenon Sep 01 '17 at 22:29