Make division by zero equal to zero

PythonDivisionZero

Python Problem Overview


How can I ignore ZeroDivisionError and make n / 0 == 0?

Python Solutions


Solution 1 - Python

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 2 - Python

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

Solution 3 - Python

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 ZeroDivisionErrors 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.

Solution 4 - Python

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 have True and a / b or 0. True and a / b is equal to a / b. a / b or 0 is equal to a / b.
  • When b == 0 we have False and a / b or 0. False and a / b is equal to False. False or 0 is equal to 0.

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

Solution 5 - Python

def foo(x, y):
    return 0 if y == 0 else x / y

Solution 6 - Python

I think if you don't want to face Zer0DivErrr, you haven't got to wait for it or go through it by using try-except expression. The quicker way is to jump over it by making your code simply not to do division when denominator becomes zero:

(if Y Z=X/Y else Z=0)

Solution 7 - Python

You can use the following :

x=0,y=0
print (y/(x or not x))

Output:

>>>x=0
>>>y=0
>>>print(y/(x or not x))
0.0
>>>x =1000
>>>print(y/(x or not x))
0.000999000999000999

not x will be false if x is not equal to 0, so at that time it divides with actual x.

Solution 8 - Python

If you are trying to divide two integers you may use :

if y !=0 :
   z = x/y
else:
    z = 0

or you can use :

z = ( x / y ) if y != 0 else 0

If you are trying to divide two lists of integers you may use :

z = [j/k if k else 0 for j, k in zip(x, y)]

where here, x and y are two lists of integers.

Solution 9 - Python

I was intrigued why ToTomire's solution would be faster. If feels like conditional_div should often be preferred for its natural language readability, but if I can understand exactly why logic_div is faster that might help me in the future. I looked to python's dis for this.

>>> conditional_div = lambda n,d: n/d if d else 0
>>> logic_div = lambda n,d: d and n/d or 0
>>> dis.dis(conditional_div)
  1           0 LOAD_FAST                1 (d)
              2 POP_JUMP_IF_FALSE       12
              4 LOAD_FAST                0 (n)
              6 LOAD_FAST                1 (d)
              8 BINARY_TRUE_DIVIDE
             10 RETURN_VALUE
        >>   12 LOAD_CONST               1 (0)
             14 RETURN_VALUE
>>> dis.dis(logic_div)
  1           0 LOAD_FAST                1 (d)
              2 POP_JUMP_IF_FALSE       12
              4 LOAD_FAST                0 (n)
              6 LOAD_FAST                1 (d)
              8 BINARY_TRUE_DIVIDE
             10 JUMP_IF_TRUE_OR_POP     14
        >>   12 LOAD_CONST               1 (0)
        >>   14 RETURN_VALUE

And it appears that logic_div should actually have an extra step. Up to '8' the two bytecodes are identical. At '10' conditional_div would just return a value whereas logic_div has to do a jump if its true and then return. Perhaps the alternative ..._OR_POP is faster than returning so some percent of the time it has a shorter last step? But the only way that ..._OR_POP would be activated is if the numerator were zero and the denominator non-zero. Both bytecodes take the same route when the denominator is zero. This doesn't feel like a satisfying conclusion. Maybe someone can explain if I'm misunderstanding something.

For reference

>>> sys.version
'3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)]'

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionoctosquidopusView Question on Stackoverflow
Solution 1 - PythondavidismView Answer on Stackoverflow
Solution 2 - PythonCory KramerView Answer on Stackoverflow
Solution 3 - PythonRick supports MonicaView Answer on Stackoverflow
Solution 4 - PythonToTamireView Answer on Stackoverflow
Solution 5 - PythontwasbrilligView Answer on Stackoverflow
Solution 6 - PythonVynylynView Answer on Stackoverflow
Solution 7 - PythonSaurav PandaView Answer on Stackoverflow
Solution 8 - Pythonmy sharkView Answer on Stackoverflow
Solution 9 - Pythonjbf81tbView Answer on Stackoverflow