Make division by zero equal to zero
You can use a try
/except
block for this.
def foo(x,y):
try:
return x/y
except ZeroDivisionError:
return 0
>>> foo(5,0)
0
>>> foo(6,2)
3.0
I think try
except
(as in Cyber's answer) is usually the best way (and more pythonic: better to ask forgiveness than to ask permission!), but here's another:
def safe_div(x,y):
if y == 0:
return 0
return x / y
One argument in favor of doing it this way, though, is if you expect ZeroDivisionError
s to happen often, checking for 0 denominator ahead of time will be a lot faster (this is python 3):
import time
def timing(func):
def wrap(f):
time1 = time.time()
ret = func(f)
time2 = time.time()
print('%s function took %0.3f ms' % (f.__name__, int((time2-time1)*1000.0)))
return ret
return wrap
def safe_div(x,y):
if y==0: return 0
return x/y
def try_div(x,y):
try: return x/y
except ZeroDivisionError: return 0
@timing
def test_many_errors(f):
print("Results for lots of caught errors:")
for i in range(1000000):
f(i,0)
@timing
def test_few_errors(f):
print("Results for no caught errors:")
for i in range(1000000):
f(i,1)
test_many_errors(safe_div)
test_many_errors(try_div)
test_few_errors(safe_div)
test_few_errors(try_div)
Output:
Results for lots of caught errors:
safe_div function took 185.000 ms
Results for lots of caught errors:
try_div function took 727.000 ms
Results for no caught errors:
safe_div function took 223.000 ms
Results for no caught errors:
try_div function took 205.000 ms
So using try
except
turns out to be 3 to 4 times slower for lots of (or really, all) errors; that is: it is 3 to 4 times slower for iterations that an error is caught. The version using the if
statement turns out to be slightly slower (10% or so) when there are few (or really, no) errors.
Check if the denominator is zero before dividing. This avoids the overhead of catching the exception, which may be more efficient if you expect to be dividing by zero a lot.
def weird_division(n, d):
return n / d if d else 0
Solution
When you want to efficient handle ZeroDivisionError
(division by zero) then you should not use exceptions or conditionals.
result = b and a / b or 0 # a / b
How it's works?
- When
b != 0
we haveTrue and a / b or 0
.True and a / b
is equal toa / b
.a / b or 0
is equal toa / b
. - When
b == 0
we haveFalse and a / b or 0
.False and a / b
is equal toFalse
.False or 0
is equal to0
.
Benchmark
Timer unit: 1e-06 s
Total time: 118.362 s
File: benchmark.py
Function: exception_div at line 3
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 @profile
4 def exception_div(a, b):
5 100000000 23419098.5 0.2 19.8 try:
6 100000000 40715642.9 0.4 34.4 return a / b
7 100000000 28910860.8 0.3 24.4 except ZeroDivisionError:
8 100000000 25316209.7 0.3 21.4 return 0
Total time: 23.638 s
File: benchmark.py
Function: conditional_div at line 10
Line # Hits Time Per Hit % Time Line Contents
==============================================================
10 @profile
11 def conditional_div(a, b):
12 100000000 23638033.3 0.2 100.0 return a / b if b else 0
Total time: 23.2162 s
File: benchmark.py
Function: logic_div at line 14
Line # Hits Time Per Hit % Time Line Contents
==============================================================
14 @profile
15 def logic_div(a, b):
16 100000000 23216226.0 0.2 100.0 return b and a / b or 0