For a machine learning application, I need to sort lists based on a value that gets updated but is initialized to 0. The problem is that parts of the updated values initially 0 are used int he formula that's used as sort-key, one of which in the denominator, so it'd throw DivisionByZero erros on the first iteration.
Since checking for 0 will be done multiple times for each element, I want to write denominator of the formula very efficient while still maintaining a reasonable degree of readability. I came up with 4 versions so far:
import random
import datetime
def generate_value_pair():
# in my case about 10% of the time b == 0
return 10**6 * random.random(), \
10**6 * random.random() * (random.random() > 0.1)
def f0(a, b):
if b != 0:
return a/b
else:
return 0
def f1(a, b):
return (not b or (a/b)+1)-1
def f2(a, b):
return b and a/b
def f3(a, b):
try:
return a/b
except:
return 0
def compare(func):
n = datetime.datetime.now()
for _ in range(10**8):
func(*generate_value_pair())
print(datetime.datetime.now() - n)
fs = [f0, f1, f2, f3]
# sanity check for new versions
# not using assert because of floating point precision at 2/7
for a, b in zip(list(range(10)), reversed(list(range(10)))):
t = (a, b)
for f in fs:
print(float(f(*t)), end='\t')
print()
for f in fs:
compare(f)
The results of this test are as follows:
0:00:36.163209
0:00:38.947623
0:00:35.436445
0:00:35.450830
Unsuprisingly f2
, which is the function with the least amount of operations and branches is fastest. Much to my surprise, f3
with try/except clocks in at a very close 2nd place, with the naive if/else f0
at 3rd and my initial attempt at improving the naive version f1
comes in at last place.
try/except is much faster than I thought, so I did another test where 50% of the cases b == 0
:
0:00:36.998776
0:00:37.043782
0:00:35.061485
0:00:41.943822
So what's slow is the throwing of the exception and what comes after, but if your case happens rarely try/except can be pretty close to "optimal", as seen above.
My Question is: Is there any faster way to do this?