# Testing whether a number is nearly a multiple of 10

I'm going through a basic python exercise, stumbled upon this query.

Given a non-negative number "num", return True if num is within 2 of a multiple of 10.

Here's the my solution:

def near_ten(num):
return (num % 10) in range(8, 10) or (num % 10) in range(0, 3)


It shows "All Correct", but I'm feeling like my code is bit digressive as I have hard-coded the "numbers within 2 of a multiple of 10".

Can one please review this line if its the right approach?

• I'm not sure I understand your solution. Multiples of 10 aren't just 0 and 10, but also 20, 30, 40, etc. – shadowtalker Nov 28 '17 at 13:30
• You could shift the values, so you need to check only one range: return ((num + 2) % 10) in range(0, 5) or return ((num + 2) % 10) < 5 – Henrik Nov 28 '17 at 13:56

I would suggest you to go further in hard coding those values: I mean I would write:

def is_near_ten(num):
return (num % 10) in [0, 1, 2, 8, 9]


You can see visually the difference (less instructions) and you can confirm that:

>>> import timeit
>>> timeit.timeit('(128 % 10) in [0, 1, 2, 8, 9]')
0.23481132300003082
>>> timeit.timeit('(128 % 10) in range(8, 10) or (128 % 10) in range(0, 3)')
1.3901589560000502


You can notice that further hard coding those values as suggested makes your function more than 5 times faster.

• Of-course, in proper code, you'd move those hardcoded values to PSEUDO_CONSTS. – Mast Nov 28 '17 at 11:50
• While a perfectly valid answer, I disagree with hardcoding the distances as a list. I think it would make more sense if one could dynamically set the 'close' value, e.g. is_near(number, limit). – Daniel Nov 28 '17 at 11:50

A hard-coded solution without lists:

def near_ten(num):
return ((num%10) <= 2) or ((num%10) >= 8)


A generalized version, as some commenters asked for:

def near_num(num,mult,diff):
return ((num%mult) <= diff) or ((num%mult) >= (mult-diff))

def near_ten(num):
return near_num(num,10,2)


The times I got for this were: (using existing answers to compare against)

>>> import timeit
>>> timeit.timeit('(128%10) in range(0,3) or (128%10) in range(8,10)')
0.5436179637908936
>>> timeit.timeit('(128%10) in [0,1,2,8,9]')
0.15247392654418945
>>> timeit.timeit('(128%10) <= 2) or ((128%10) >= (10-2))')
0.11723899841308594


So, it seems a little faster than even the hard-coded list.

I thought about adding a variable to store the value of (num%mult), but figure that a smart compiler should automatically put that in a temporary variable for reuse.

• I thought about adding a variable to store the (num%mult), but figure that a smart compiler should automatically put that in a temporary variable for reuse. So, I am curious as to opinions on how that would affect speed, memory, and (most importantly to me) readability. – Ghost8472 Nov 28 '17 at 16:46
• I added the context from your comment in your post - Refer to the section When shouldn't I comment? on Comment everywhere. You could potentially post a new question if you have working code, and reference this post... – Sᴀᴍ Onᴇᴌᴀ Nov 28 '17 at 16:49
• @SamOnela thanks for linking to that article on commenting, I hadn't seen it yet. I went back and forth on whether to edit my post, or add a comment. I think I can argue my comment was part of "Add relevant but minor or transient information to a post" because my comment addresses an alternative style to what I advocated. I fixed your edit, as it broke the context of my post. – Ghost8472 Nov 28 '17 at 17:09
• okay- sorry about that. – Sᴀᴍ Onᴇᴌᴀ Nov 28 '17 at 17:10
• @SamOnela thank you. Sorry I was being snippy. I do think you are right that my comment should have been part of the post. Also, thank you for pointing out the context issues, and I will try to avoid asking new questions in my answers/comments. – Ghost8472 Nov 28 '17 at 17:20