I was at a loss when writing the program myself, so I will write it down as a memo. If you know a better solution, please point it out.
※environment
When I do normal division by zero in Python, I get a ZeroDivisionError
.
python
try:
divided = 1 / 0
except ZeroDivisionError as e:
print(f'ZeroDivisionError: {e}')
# -> ZeroDivisionError: division by zero
On the other hand, if you divide by zero with numpy, RuntimeWarning
will occur, but the result will be output without stopping the processing.
python
import numpy as np
divided = 1 / np.array(0)
print(devided)
# -> inf
# -> RuntimeWarning: divide by zero encountered in true_divide
The result of the calculation of 1 / np.array (0)
is the object numpy.inf
which represents infinity with numpy.
It gives a warning, but it doesn't stop the process, so it feels halfway. Perhaps it is left to the user to say, "I can calculate it, but I'll give you a warning. I'll leave it to you."
So, let's think about what to do when you want to stop the process and when you allow the process and ignore the warning.
You can use warnings.simplefilter
to make RuntimeWarning
an exception or ignore it.
--When you want to treat it as an exception and stop processing
python
import warnings
import numpy as np
warnings.simplefilter('error', category=RuntimeWarning) #Set Runtime Warning as exception
a = np.array(0) #Variables that are not expected to contain 0
divided = 1 / a
print(divided)
# -> RuntimeWarning: divide by zero encountered in true_divide
# divided = 1 /Processing stops at a and print(divided)Is not executed
--When you want to allow calculations and ignore warnings
python
import warnings
import numpy as np
warnings.simplefilter('ignore', category=RuntimeWarning) #Set Runtime Warning to ignore
a = np.array(0) #Variables that may contain 0
divided = 1 / a
print(divided)
# -> inf
#No warning is issued and processing continues
However, at this time, the control is applied to RuntimeWarning
other than division by zero, so there is a risk that the bug cannot be captured, especially if it is ignored. So I think about another method
(In response to the comment, I added numpy.seteer
.)
You can use numpy.seteer
to set finer control of Warning
.
python
import numpy as np
np.seterr(divide='ignore') #Ignore only Division by Zero Runtime Warning
a = np.array(0)
divided = 1 / a
print(divided)
# -> inf
Now you can add control only to division by zero. The complexity of ʻimporting
warningshas also been eliminated. However, in this case this control applies to the entire source code. If possible, I want to minimize the scope of control. You can switch the control by writing
numpy.seterr` before and after division, but consider a smarter description.
(This is also the part added from the comments pointed out)
By using numpy.errstate
, it is possible to control by the context manager.
python
import numpy as np
a = np.array(0)
with np.errstate(divide='ignore'): #Apply control only within scope
divided = 1 / a
print(divided)
# -> inf
divided = 1 / a #Runtime Warning occurs because it is out of scope for ignoring
# -> RuntimeWarning: divide by zero encountered in true_divide
This will reduce the scope of control changes and supplement bugs caused by division by zero elsewhere (not allowed).
In the example, we considered division of numbers for clarity, but you can control array division as well.
python
import numpy as np
a = np.array([1, 2, 0])
with np.errstate(divide='ignore'): #Apply control only within scope
divided = 1 / a
print(divided)
# -> [1. 0.5 inf]
If you want to divide one number, you can simply write an if statement, but in the case of an array, that is difficult, so I think this control method will be useful.
At first, I didn't know numpy.errstate
and thought about how to write it as follows.
python
import numpy as np
a = np.array([1, 2, 0])
divided = np.full(len(a), np.inf) #All elements are np.Make an array of inf
nonzero_indices = np.where(a != 0)[0] #An array of indexes with non-zero elements in a
divided[nonzero_indices] = 1 / a[nonzero_indices] # nonzero_Rewrite only the elements of array to division
print(divided)
# -> [1. 0.5 inf]
I wanted to avoid the warning of division by zero only, but it seems redundant.
I want to be able to remember and use useful methods like numpy.errstate
.